From 3c90f6a30d83e1803f34497136003bc3c0b3787e Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 13:34:46 +0100 Subject: [PATCH] miniupnpd/natpmp.c: avoid hang when all external ports in use reorganize a bit --- miniupnpd/Changelog.txt | 3 +++ miniupnpd/natpmp.c | 55 ++++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 36594c2..c6b04ea 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,5 +1,8 @@ $Id: Changelog.txt,v 1.352 2014/02/24 18:41:23 nanard Exp $ +2014/02/28: + natpmp : avoid hang when all external ports in use + 2014/02/24: Defaulting to SSDP_RESPOND_SAME_VERSION diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 6764732..c3d26ce 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -205,7 +205,6 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, int proto; char iaddr_old[16]; unsigned short iport_old; - unsigned short eport_first; unsigned int timestamp; iport = ntohs(*((uint16_t *)(req+4))); @@ -268,12 +267,14 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, || !check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { resp[3] = 2; /* Not Authorized/Refused */ } else { + unsigned short eport_first; + char desc[64]; eport_first = eport; do { r = get_redirect_rule(ext_if_name, eport, proto, - iaddr_old, sizeof(iaddr_old), - &iport_old, 0, 0, 0, 0, - ×tamp, 0, 0); + iaddr_old, sizeof(iaddr_old), + &iport_old, 0, 0, 0, 0, + ×tamp, 0, 0); if(r==0) { if(strcmp(senderaddrstr, iaddr_old)==0 && iport==iport_old) { @@ -288,42 +289,40 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } else { eport++; if(eport == eport_first) { /* no external port available */ - syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); + syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); resp[3] = 3; /* Failure */ break; } continue; } } - { /* do the redirection */ - char desc[64]; + /* do the redirection */ #if 0 - timestamp = (unsigned)(time(NULL) - startup_time) - + lifetime; - snprintf(desc, sizeof(desc), "NAT-PMP %u", timestamp); + timestamp = (unsigned)(time(NULL) - startup_time) + + lifetime; + snprintf(desc, sizeof(desc), "NAT-PMP %u", timestamp); #else - timestamp = time(NULL) + lifetime; - snprintf(desc, sizeof(desc), "NAT-PMP %hu %s", - eport, (proto==IPPROTO_TCP)?"tcp":"udp"); + timestamp = time(NULL) + lifetime; + snprintf(desc, sizeof(desc), "NAT-PMP %hu %s", + eport, (proto==IPPROTO_TCP)?"tcp":"udp"); #endif - /* TODO : check return code */ - if(upnp_redirect_internal(NULL, eport, senderaddrstr, - iport, proto, desc, - timestamp) < 0) { - syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc); - resp[3] = 3; /* Failure */ + /* TODO : check return code */ + if(upnp_redirect_internal(NULL, eport, senderaddrstr, + iport, proto, desc, + timestamp) < 0) { + syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc); + resp[3] = 3; /* Failure */ #if 0 - } else if( !nextnatpmptoclean_eport - || timestamp < nextnatpmptoclean_timestamp) { - nextnatpmptoclean_timestamp = timestamp; - nextnatpmptoclean_eport = eport; - nextnatpmptoclean_proto = proto; + } else if( !nextnatpmptoclean_eport + || timestamp < nextnatpmptoclean_timestamp) { + nextnatpmptoclean_timestamp = timestamp; + nextnatpmptoclean_eport = eport; + nextnatpmptoclean_proto = proto; #endif - } - break; } + break; } while(r==0); } *((uint16_t *)(resp+8)) = htons(iport); /* private port */