From be9584d156b8313227314b4dbd89308398da4e58 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 13 May 2014 20:04:00 +0100 Subject: [PATCH 1/5] Fix formatting in areas the next commit will touch --- miniupnpc/upnpc.c | 28 ++++++++++++++-------------- miniupnpc/upnpcommands.c | 14 +++++++------- miniupnpc/upnpcommands.h | 18 +++++++++--------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/miniupnpc/upnpc.c b/miniupnpc/upnpc.c index 70c9a54..4e1cc9b 100644 --- a/miniupnpc/upnpc.c +++ b/miniupnpc/upnpc.c @@ -223,13 +223,13 @@ static void NewListRedirections(struct UPNPUrls * urls, * 3 - Add port mapping * 4 - get this port mapping from the IGD */ static void 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) + struct IGDdatas * data, + const char * iaddr, + const char * iport, + const char * eport, + const char * proto, + const char * leaseDuration, + const char * description, { char externalIPAddress[40]; char intClient[40]; @@ -265,10 +265,10 @@ static void SetRedirectAndTest(struct UPNPUrls * urls, eport, iport, iaddr, r, strupnperror(r)); r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - data->first.servicetype, - eport, proto, NULL/*remoteHost*/, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); + data->first.servicetype, + eport, proto, NULL/*remoteHost*/, + intClient, intPort, NULL/*desc*/, + NULL/*enabled*/, duration); if(r!=UPNPCOMMAND_SUCCESS) printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", r, strupnperror(r)); @@ -283,8 +283,8 @@ static void SetRedirectAndTest(struct UPNPUrls * urls, static void RemoveRedirect(struct UPNPUrls * urls, struct IGDdatas * data, - const char * eport, - const char * proto) + const char * eport, + const char * proto) { int r; if(!proto || !eport) @@ -549,7 +549,7 @@ int main(int argc, char ** argv) fprintf(stderr, " \t%s [options] -d external_port protocol [port2 protocol2] [...]\n\t\tDelete port redirection\n", argv[0]); fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]); fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]); - fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings, IGD v2)\n", argv[0]); + fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]); fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]); diff --git a/miniupnpc/upnpcommands.c b/miniupnpc/upnpcommands.c index ad69781..aa9e245 100644 --- a/miniupnpc/upnpcommands.c +++ b/miniupnpc/upnpcommands.c @@ -335,13 +335,13 @@ UPNP_GetExternalIPAddress(const char * controlURL, LIBSPEC int 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) + const char * extPort, + const char * inPort, + const char * inClient, + const char * desc, + const char * proto, + const char * remoteHost, + const char * leaseDuration) { struct UPNParg * AddPortMappingArgs; char * buffer; diff --git a/miniupnpc/upnpcommands.h b/miniupnpc/upnpcommands.h index 93d9f3d..7d8f18e 100644 --- a/miniupnpc/upnpcommands.h +++ b/miniupnpc/upnpcommands.h @@ -123,13 +123,13 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL, */ LIBSPEC int 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); + const char * extPort, + const char * inPort, + const char * inClient, + const char * desc, + const char * proto, + const char * remoteHost, + const char * leaseDuration); /* UPNP_DeletePortMapping() * Use same argument values as what was used for AddPortMapping(). @@ -145,8 +145,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, * 714 NoSuchEntryInArray - The specified value does not exist in the array */ LIBSPEC int UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, - const char * extPort, const char * proto, - const char * remoteHost); + const char * extPort, const char * proto, + const char * remoteHost); /* UPNP_GetPortMappingNumberOfEntries() * not supported by all routers */ From b9362f32a7ec6580d2fc80f9d8ab4ffa551f662a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 13 May 2014 20:35:00 +0100 Subject: [PATCH 2/5] Add support for IGD2 AddAnyPortMapping and DeletePortMappingRange Added python bindings for both AddAnyPortMapping and DeletePortMappingRange --- miniupnpc/miniupnpcmodule.c | 73 +++++++++++++++++++++++ miniupnpc/upnpc.c | 81 +++++++++++++++++++++----- miniupnpc/upnpcommands.c | 113 ++++++++++++++++++++++++++++++++++++ miniupnpc/upnpcommands.h | 54 +++++++++++++++++ miniupnpc/upnperrors.c | 3 + 5 files changed, 311 insertions(+), 13 deletions(-) diff --git a/miniupnpc/miniupnpcmodule.c b/miniupnpc/miniupnpcmodule.c index 4654c98..1ab563a 100644 --- a/miniupnpc/miniupnpcmodule.c +++ b/miniupnpc/miniupnpcmodule.c @@ -265,6 +265,42 @@ Py_END_ALLOW_THREADS } } +/* AddAnyPortMapping(externalPort, protocol, internalHost, internalPort, desc, + * remoteHost) + * protocol is 'UDP' or 'TCP' */ +static PyObject * +UPnP_addanyportmapping(UPnPObject *self, PyObject *args) +{ + char extPort[6]; + unsigned short ePort; + char inPort[6]; + unsigned short iPort; + char reservedPort[6]; + const char * proto; + const char * host; + const char * desc; + const char * remoteHost; + const char * leaseDuration = "0"; + int r; + if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto, &host, &iPort, &desc, &remoteHost)) + return NULL; +Py_BEGIN_ALLOW_THREADS + sprintf(extPort, "%hu", ePort); + sprintf(inPort, "%hu", iPort); + r = UPNP_AddAnyPortMapping(self->urls.controlURL, self->data.first.servicetype, + extPort, inPort, host, desc, proto, + remoteHost, leaseDuration, reservedPort); +Py_END_ALLOW_THREADS + if(r==UPNPCOMMAND_SUCCESS) { + return Py_BuildValue("i", atoi(reservedPort)); + } else { + /* TODO: have our own exception type ! */ + PyErr_SetString(PyExc_Exception, strupnperror(r)); + return NULL; + } +} + + /* DeletePortMapping(extPort, proto, removeHost='') * proto = 'UDP', 'TCP' */ static PyObject * @@ -291,6 +327,37 @@ Py_END_ALLOW_THREADS } } +/* DeletePortMappingRange(extPort, proto, removeHost='') + * proto = 'UDP', 'TCP' */ +static PyObject * +UPnP_deleteportmappingrange(UPnPObject *self, PyObject *args) +{ + char extPortStart[6]; + unsigned short ePortStart; + char extPortEnd[6]; + unsigned short ePortEnd; + const char * proto; + unsigned char manage; + char manageStr[1]; + int r; + if(!PyArg_ParseTuple(args, "HHsb", &ePortStart, &ePortEnd, &proto, &manage)) + return NULL; +Py_BEGIN_ALLOW_THREADS + sprintf(extPortStart, "%hu", ePortStart); + sprintf(extPortEnd, "%hu", ePortEnd); + sprintf(manageStr, "%hhu", manage); + r = UPNP_DeletePortMappingRange(self->urls.controlURL, self->data.first.servicetype, + extPortStart, extPortEnd, proto, manageStr); +Py_END_ALLOW_THREADS + if(r==UPNPCOMMAND_SUCCESS) { + Py_RETURN_TRUE; + } else { + /* TODO: have our own exception type ! */ + PyErr_SetString(PyExc_Exception, strupnperror(r)); + return NULL; + } +} + static PyObject * UPnP_getportmappingnumberofentries(UPnPObject *self) { @@ -429,9 +496,15 @@ static PyMethodDef UPnP_methods[] = { {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS, "add a port mapping" }, + {"addanyportmapping", (PyCFunction)UPnP_addanyportmapping, METH_VARARGS, + "add a port mapping, IGD to select alternative if necessary" + }, {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS, "delete a port mapping" }, + {"deleteportmappingrange", (PyCFunction)UPnP_deleteportmappingrange, METH_VARARGS, + "delete a range of port mappings" + }, {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS, "-- non standard --" }, diff --git a/miniupnpc/upnpc.c b/miniupnpc/upnpc.c index 4e1cc9b..90cecbf 100644 --- a/miniupnpc/upnpc.c +++ b/miniupnpc/upnpc.c @@ -230,10 +230,12 @@ static void SetRedirectAndTest(struct UPNPUrls * urls, 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; @@ -257,12 +259,23 @@ static void SetRedirectAndTest(struct UPNPUrls * urls, else printf("GetExternalIPAddress failed.\n"); - r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype, - eport, iport, iaddr, description, - proto, 0, leaseDuration); - if(r!=UPNPCOMMAND_SUCCESS) - printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", - eport, iport, iaddr, r, strupnperror(r)); + 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 { + r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype, + eport, iport, iaddr, description, + proto, 0, leaseDuration); + if(r!=UPNPCOMMAND_SUCCESS) + printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", + eport, iport, iaddr, r, strupnperror(r)); + } r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, data->first.servicetype, @@ -302,6 +315,32 @@ RemoveRedirect(struct UPNPUrls * urls, printf("UPNP_DeletePortMapping() returned : %d\n", r); } +static void +RemoveRedirectRange(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * ePortStart, char const * ePortEnd, + const char * proto, const char * manage) +{ + int r; + + if (!manage) + manage = "0"; + + if(!proto || !ePortStart || !ePortEnd) + { + fprintf(stderr, "invalid arguments\n"); + return; + } + proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "protocol invalid\n"); + return; + } + r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage); + printf("UPNP_DeletePortMappingRange() returned : %d\n", r); +} + /* IGD:2, functions for service WANIPv6FirewallControl:1 */ static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data) { @@ -550,6 +589,8 @@ int main(int argc, char ** argv) fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]); fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]); fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]); + fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]); fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]); fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]); @@ -631,10 +672,10 @@ int main(int argc, char ** argv) break; case 'a': SetRedirectAndTest(&urls, &data, - commandargv[0], commandargv[1], - commandargv[2], commandargv[3], - (commandargc > 4)?commandargv[4]:"0", - description); + commandargv[0], commandargv[1], + commandargv[2], commandargv[3], + (commandargc > 4)?commandargv[4]:"0", + description, 0); break; case 'd': for(i=0; i 4)?commandargv[4]:"0", + description, 1); + break; + case 'N': + if (commandargc < 3) + fprintf(stderr, "too few arguments\n"); + + RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2], + commandargc > 3 ? commandargv[3] : NULL); + break; case 's': GetConnectionStatus(&urls, &data); break; @@ -650,9 +705,9 @@ int main(int argc, char ** argv) { /*printf("port %s protocol %s\n", argv[i], argv[i+1]);*/ SetRedirectAndTest(&urls, &data, - lanaddr, commandargv[i], - commandargv[i], commandargv[i+1], "0", - description); + lanaddr, commandargv[i], + commandargv[i], commandargv[i+1], "0", + description, 0); } break; case 'A': diff --git a/miniupnpc/upnpcommands.c b/miniupnpc/upnpcommands.c index aa9e245..b35e98b 100644 --- a/miniupnpc/upnpcommands.c +++ b/miniupnpc/upnpcommands.c @@ -394,6 +394,73 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, return ret; } +LIBSPEC int +UPNP_AddAnyPortMapping(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, + char * reservedPort) +{ + struct UPNParg * AddPortMappingArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!inPort || !inClient || !proto || !extPort) + return UPNPCOMMAND_INVALID_ARGS; + + AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); + AddPortMappingArgs[0].elt = "NewRemoteHost"; + AddPortMappingArgs[0].val = remoteHost; + AddPortMappingArgs[1].elt = "NewExternalPort"; + AddPortMappingArgs[1].val = extPort; + AddPortMappingArgs[2].elt = "NewProtocol"; + AddPortMappingArgs[2].val = proto; + AddPortMappingArgs[3].elt = "NewInternalPort"; + AddPortMappingArgs[3].val = inPort; + AddPortMappingArgs[4].elt = "NewInternalClient"; + AddPortMappingArgs[4].val = inClient; + AddPortMappingArgs[5].elt = "NewEnabled"; + AddPortMappingArgs[5].val = "1"; + AddPortMappingArgs[6].elt = "NewPortMappingDescription"; + AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; + AddPortMappingArgs[7].elt = "NewLeaseDuration"; + AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "AddAnyPortMapping", AddPortMappingArgs, + &bufsize))) { + free(AddPortMappingArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } else { + char *p; + + p = GetValueFromNameValueList(&pdata, "NewReservedPort"); + if(p) { + strncpy(reservedPort, p, 6); + reservedPort[5] = '\0'; + ret = UPNPCOMMAND_SUCCESS; + } else { + ret = UPNPCOMMAND_INVALID_RESPONSE; + } + } + ClearNameValueList(&pdata); + free(AddPortMappingArgs); + return ret; +} + LIBSPEC int UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, @@ -438,6 +505,52 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, return ret; } +LIBSPEC int +UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, + const char * extPortStart, const char * extPortEnd, + const char * proto, + const char * manage) +{ + struct UPNParg * DeletePortMappingArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!extPortStart || !extPortEnd || !proto || !manage) + return UPNPCOMMAND_INVALID_ARGS; + + DeletePortMappingArgs = calloc(5, sizeof(struct UPNParg)); + DeletePortMappingArgs[0].elt = "NewStartPort"; + DeletePortMappingArgs[0].val = extPortStart; + DeletePortMappingArgs[1].elt = "NewEndPort"; + DeletePortMappingArgs[1].val = extPortEnd; + DeletePortMappingArgs[2].elt = "NewProtocol"; + DeletePortMappingArgs[2].val = proto; + DeletePortMappingArgs[3].elt = "NewManage"; + DeletePortMappingArgs[3].val = manage; + + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "DeletePortMappingRange", + DeletePortMappingArgs, &bufsize))) { + free(DeletePortMappingArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } else { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(DeletePortMappingArgs); + return ret; +} + LIBSPEC int UPNP_GetGenericPortMappingEntry(const char * controlURL, const char * servicetype, diff --git a/miniupnpc/upnpcommands.h b/miniupnpc/upnpcommands.h index 7d8f18e..8ca3576 100644 --- a/miniupnpc/upnpcommands.h +++ b/miniupnpc/upnpcommands.h @@ -17,6 +17,7 @@ #define UPNPCOMMAND_UNKNOWN_ERROR (-1) #define UPNPCOMMAND_INVALID_ARGS (-2) #define UPNPCOMMAND_HTTP_ERROR (-3) +#define UPNPCOMMAND_INVALID_RESPONSE (-4) #ifdef __cplusplus extern "C" { @@ -131,6 +132,40 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * remoteHost, const char * leaseDuration); +/* UPNP_AddAnyPortMapping() + * if desc is NULL, it will be defaulted to "libminiupnpc" + * remoteHost is usually NULL because IGD don't support it. + * + * Return values : + * 0 : SUCCESS + * NON ZERO : ERROR. Either an UPnP error code or an unknown error. + * + * List of possible UPnP errors for AddPortMapping : + * errorCode errorDescription (short) - Description (long) + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization and + * the sender was not authorized. + * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be + * wild-carded + * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded + * 728 NoPortMapsAvailable - There are not enough free ports available to + * complete port mapping. + * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed + * due to conflict with other mechanisms. + * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded + */ +LIBSPEC int +UPNP_AddAnyPortMapping(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, + char * reservedPort); + /* UPNP_DeletePortMapping() * Use same argument values as what was used for AddPortMapping(). * remoteHost is usually NULL because IGD don't support it. @@ -148,6 +183,25 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, const char * remoteHost); +/* UPNP_DeletePortRangeMapping() + * Use same argument values as what was used for AddPortMapping(). + * remoteHost is usually NULL because IGD don't support it. + * Return Values : + * 0 : SUCCESS + * NON ZERO : error. Either an UPnP error code or an undefined error. + * + * List of possible UPnP errors for DeletePortMapping : + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. + * 730 PortMappingNotFound - This error message is returned if no port + * mapping is found in the specified range. + * 733 InconsistentParameters - NewStartPort and NewEndPort values are not consistent. */ +LIBSPEC int +UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, + const char * extPortStart, const char * extPortEnd, + const char * proto, + const char * manage); + /* UPNP_GetPortMappingNumberOfEntries() * not supported by all routers */ LIBSPEC int diff --git a/miniupnpc/upnperrors.c b/miniupnpc/upnperrors.c index d459fe0..40a2e78 100644 --- a/miniupnpc/upnperrors.c +++ b/miniupnpc/upnperrors.c @@ -24,6 +24,9 @@ const char * strupnperror(int err) case UPNPCOMMAND_INVALID_ARGS: s = "Miniupnpc Invalid Arguments"; break; + case UPNPCOMMAND_INVALID_RESPONSE: + s = "Miniupnpc Invalid response"; + break; case UPNPDISCOVER_SOCKET_ERROR: s = "Miniupnpc Socket error"; break; From 0490d162213a7747e7ffe39d3fccc3ebc626c4fd Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 13 May 2014 21:04:14 +0100 Subject: [PATCH 3/5] Don't print garbage values on failure --- miniupnpc/upnpc.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/miniupnpc/upnpc.c b/miniupnpc/upnpc.c index 90cecbf..e34b33c 100644 --- a/miniupnpc/upnpc.c +++ b/miniupnpc/upnpc.c @@ -251,13 +251,13 @@ static void SetRedirectAndTest(struct UPNPUrls * urls, return; } - UPNP_GetExternalIPAddress(urls->controlURL, - data->first.servicetype, - externalIPAddress); - if(externalIPAddress[0]) - printf("ExternalIPAddress = %s\n", externalIPAddress); - else + r = UPNP_GetExternalIPAddress(urls->controlURL, + data->first.servicetype, + externalIPAddress); + if(r!=UPNPCOMMAND_SUCCESS) printf("GetExternalIPAddress failed.\n"); + else + printf("ExternalIPAddress = %s\n", externalIPAddress); if (addAny) { r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype, @@ -285,8 +285,7 @@ static void SetRedirectAndTest(struct UPNPUrls * urls, if(r!=UPNPCOMMAND_SUCCESS) printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", r, strupnperror(r)); - - if(intClient[0]) { + else { 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); From 20f1e070a1d123a43b58857eaccc202734c4553b Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 13 May 2014 21:29:19 +0100 Subject: [PATCH 4/5] Don't call deletePortMapping method for deletePortMappingRange Length of strings needs to match before doing comparison, else we can stop early on a substring of the one were trying to match. --- miniupnpd/upnpsoap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/miniupnpd/upnpsoap.c b/miniupnpd/upnpsoap.c index 9f6eda5..47a4f14 100644 --- a/miniupnpd/upnpsoap.c +++ b/miniupnpd/upnpsoap.c @@ -2014,6 +2014,11 @@ ExecuteSoapAction(struct upnphttp * h, const char * action, int n) while(soapMethods[i].methodName) { len = strlen(soapMethods[i].methodName); + if(len != methodlen) + { + i++; + continue; + } if(strncmp(p, soapMethods[i].methodName, len) == 0) { #ifdef DEBUG From f27dd4597326cc2b791768dd332c3e3aacc382ea Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Tue, 13 May 2014 21:29:49 +0100 Subject: [PATCH 5/5] Return 730 error where appropriate, and output helpful debug --- miniupnpd/upnpsoap.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/miniupnpd/upnpsoap.c b/miniupnpd/upnpsoap.c index 47a4f14..e710f0e 100644 --- a/miniupnpd/upnpsoap.c +++ b/miniupnpd/upnpsoap.c @@ -772,12 +772,23 @@ DeletePortMappingRange(struct upnphttp * h, const char * action) return; } + syslog(LOG_INFO, "%s: deleting external ports: %hu-%hu, protocol: %s", + action, startport, endport, protocol); + port_list = upnp_get_portmappings_in_range(startport, endport, protocol, &number); + if(number == 0) + { + SoapError(h, 730, "PortMappingNotFound"); + ClearNameValueList(&data); + return; + } + for(i = 0; i < number; i++) { r = upnp_delete_redirection(port_list[i], protocol); - /* TODO : check return value for errors */ + syslog(LOG_INFO, "%s: deleting external port: %hu, protocol: %s: %s", + action, port_list[i], protocol, r < 0 ? "failed" : "ok"); } free(port_list); BuildSendAndCloseSoapResp(h, resp, sizeof(resp)-1);