miniupnpd: AddAnyPortMapping() tries port above and below requested port

fixes #465
if the requested port is n, it will tries successively :
n, n+1, n-1, n+2, n-2, n+3, n-3, etc.
This commit is contained in:
Thomas Bernard 2020-06-20 16:30:38 +02:00
parent 1e7fb305b6
commit de71eef493
No known key found for this signature in database
GPG Key ID: 0FF11B67A5C0863C
1 changed files with 22 additions and 7 deletions

View File

@ -586,7 +586,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;
unsigned short iport, eport, eport_below, eport_above;
const char * leaseduration_str;
unsigned int leaseduration;
@ -669,22 +669,37 @@ AddAnyPortMapping(struct upnphttp * h, const char * action, const char * ns)
}
}
/* TODO : accept a different external port
* have some smart strategy to choose the port */
/* 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==-2 || r==-3) && eport < 65535) {
/* next port if -2 already redirected or -3 permission check failed */
eport++;
} else {
if (r == 0 || r == -1) {
/* OK or failure : Stop */
break;
}
/* r : -2 / -4 already redirected or -3 permission check failed */
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;
}
/* loop invariant :
* eport is equal to either eport_below or eport_above (or both) */
}
ClearNameValueList(&data);
switch(r)
{
case 1: /* exhausted possible mappings */
SoapError(h, 728, "NoPortMapsAvailable");
break;
case 0: /* success */
bodylen = snprintf(body, sizeof(body), resp,
action, ns, /*SERVICE_TYPE_WANIPC,*/