Merge branch 'issue-465' into master
This commit is contained in:
commit
1008ed1117
|
@ -1,7 +1,7 @@
|
|||
/* $Id: upnppermissions.c,v 1.18 2014/03/07 10:43:29 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2014 Thomas Bernard
|
||||
* (c) 2006-2020 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
|
@ -262,3 +262,44 @@ check_upnp_rule_against_permissions(const struct upnpperm * permary,
|
|||
return 1; /* Default : accept */
|
||||
}
|
||||
|
||||
void
|
||||
get_permitted_ext_ports(uint32_t * allowed,
|
||||
const struct upnpperm * permary, int n_perms,
|
||||
in_addr_t addr, u_short iport)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* build allowed external ports array */
|
||||
memset(allowed, 0xff, 65536 / 8); /* everything allowed by default */
|
||||
|
||||
for (i = n_perms - 1; i >= 0; i--)
|
||||
{
|
||||
if( (addr & permary[i].mask.s_addr)
|
||||
!= (permary[i].address.s_addr & permary[i].mask.s_addr) )
|
||||
continue;
|
||||
if( (iport < permary[i].iport_min) || (permary[i].iport_max < iport))
|
||||
continue;
|
||||
for (j = (int)permary[i].eport_min ; j <= (int)permary[i].eport_max; )
|
||||
{
|
||||
if ((j % 32) == 0 && ((int)permary[i].eport_max >= (j + 31)))
|
||||
{
|
||||
/* 32bits at once */
|
||||
allowed[j / 32] = (permary[i].type == UPNPPERM_ALLOW) ? 0xffffffff : 0;
|
||||
j += 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
/* one bit at once */
|
||||
if (permary[i].type == UPNPPERM_ALLOW)
|
||||
allowed[j / 32] |= (1 << (j % 32));
|
||||
else
|
||||
allowed[j / 32] &= ~(1 << (j % 32));
|
||||
j++;
|
||||
}
|
||||
while ((j % 32) != 0 && (j <= (int)permary[i].eport_max));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Id: upnppermissions.h,v 1.10 2014/03/07 10:43:29 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2014 Thomas Bernard
|
||||
* (c) 2006-2020 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
|
@ -45,6 +45,14 @@ check_upnp_rule_against_permissions(const struct upnpperm * permary,
|
|||
u_short eport, struct in_addr address,
|
||||
u_short iport);
|
||||
|
||||
/**
|
||||
* Build an array of all allowed external ports (for the address and internal port)
|
||||
*/
|
||||
void
|
||||
get_permitted_ext_ports(uint32_t * allowed,
|
||||
const struct upnpperm * permary, int n_perms,
|
||||
in_addr_t addr, u_short iport);
|
||||
|
||||
#ifdef USE_MINIUPNPDCTL
|
||||
void
|
||||
write_permlist(int fd, const struct upnpperm * permary,
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "upnpsoap.h"
|
||||
#include "upnpreplyparse.h"
|
||||
#include "upnpredirect.h"
|
||||
#include "upnppermissions.h"
|
||||
#include "upnppinhole.h"
|
||||
#include "getifaddr.h"
|
||||
#include "getifstats.h"
|
||||
|
@ -586,7 +587,7 @@ AddAnyPortMapping(struct upnphttp * h, const char * action, const char * ns)
|
|||
struct NameValueParserData data;
|
||||
const char * int_ip, * int_port, * ext_port, * protocol, * desc;
|
||||
const char * r_host;
|
||||
unsigned short iport, eport, eport_below, eport_above;
|
||||
unsigned short iport, eport;
|
||||
const char * leaseduration_str;
|
||||
unsigned int leaseduration;
|
||||
|
||||
|
@ -674,26 +675,41 @@ AddAnyPortMapping(struct upnphttp * h, const char * action, const char * ns)
|
|||
|
||||
/* first try the port asked in request, then
|
||||
* try +1, -1, +2, -2, etc. */
|
||||
eport_above = eport_below = eport;
|
||||
for(;;) {
|
||||
r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration);
|
||||
if (r == 0 || r == -1) {
|
||||
/* OK or failure : Stop */
|
||||
break;
|
||||
r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration);
|
||||
if (r != 0 && r != -1) {
|
||||
unsigned short eport_below, eport_above;
|
||||
struct in_addr address;
|
||||
uint32_t allowed_eports[65536 / 32];
|
||||
|
||||
if(inet_aton(int_ip, &address) <= 0) {
|
||||
syslog(LOG_ERR, "inet_aton(%s) FAILED", int_ip);
|
||||
}
|
||||
/* r : -2 / -4 already redirected or -3 permission check failed */
|
||||
if (eport_below <= 1 && eport_above == 65535) {
|
||||
/* all possible ports tried */
|
||||
r = 1;
|
||||
break;
|
||||
get_permitted_ext_ports(allowed_eports, upnppermlist, num_upnpperm,
|
||||
address.s_addr, iport);
|
||||
eport_above = eport_below = eport;
|
||||
for(;;) {
|
||||
/* loop invariant
|
||||
* eport is equal to either eport_below or eport_above (or both) */
|
||||
if (eport_below <= 1 && eport_above == 65535) {
|
||||
/* all possible ports tried */
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
if (eport_above == 65535 || (eport > eport_below && eport_below > 1)) {
|
||||
eport = --eport_below;
|
||||
} else {
|
||||
eport = ++eport_above;
|
||||
}
|
||||
if (!(allowed_eports[eport / 32] & ((uint32_t)1U << (eport % 32))))
|
||||
continue; /* not allowed */
|
||||
r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration);
|
||||
if (r == 0 || r == -1) {
|
||||
/* OK or failure : Stop */
|
||||
break;
|
||||
}
|
||||
/* r : -2 / -4 already redirected or -3 permission check failed :
|
||||
* continue */
|
||||
}
|
||||
if (eport_above == 65535 || (eport > eport_below && eport_below > 1)) {
|
||||
eport = --eport_below;
|
||||
} else {
|
||||
eport = ++eport_above;
|
||||
}
|
||||
/* loop invariant :
|
||||
* eport is equal to either eport_below or eport_above (or both) */
|
||||
}
|
||||
|
||||
ClearNameValueList(&data);
|
||||
|
|
Loading…
Reference in New Issue