miniupnpd/natpmp.c: Properly implements NAT-PMP mapping removal

fixes #97
This commit is contained in:
Thomas Bernard 2014-10-23 17:57:16 +02:00
parent 8baf8d351a
commit 350ca199c4
2 changed files with 34 additions and 34 deletions

View File

@ -1,5 +1,8 @@
$Id: Changelog.txt,v 1.379 2014/10/22 08:52:17 nanard Exp $ $Id: Changelog.txt,v 1.379 2014/10/22 08:52:17 nanard Exp $
2014/10/23:
Properly implements NAT-PMP mapping removal according to RCF6886
2014/10/22: 2014/10/22:
Discard NAT-PMP packets coming from the WAN Discard NAT-PMP packets coming from the WAN
Send SSDP announces to IPv6 link-local, site-local Send SSDP announces to IPv6 link-local, site-local

View File

@ -306,33 +306,40 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
"%hu->%s:%hu %s lifetime=%us", "%hu->%s:%hu %s lifetime=%us",
eport, senderaddrstr, iport, eport, senderaddrstr, iport,
(req[1]==1)?"udp":"tcp", lifetime); (req[1]==1)?"udp":"tcp", lifetime);
if(eport==0)
eport = iport;
/* TODO: accept port mapping if iport ok but eport not ok /* TODO: accept port mapping if iport ok but eport not ok
* (and set eport correctly) */ * (and set eport correctly) */
if(lifetime == 0) { if(lifetime == 0) {
/* remove the mapping */ /* remove the mapping */
if(iport == 0) { /* RFC6886 :
/* remove all the mappings for this client */ * A client MAY also send an explicit packet to request deletion of a
int index = 0; * mapping that is no longer needed. A client requests explicit
unsigned short eport2, iport2; * deletion of a mapping by sending a message to the NAT gateway
char iaddr2[16]; * requesting the mapping, with the Requested Lifetime in Seconds set to
int proto2; * zero. The Suggested External Port MUST be set to zero by the client
char desc[64]; * on sending, and MUST be ignored by the gateway on reception. */
while(get_redirect_rule_by_index(index, 0, int index = 0;
&eport2, iaddr2, sizeof(iaddr2), unsigned short eport2, iport2;
&iport2, &proto2, char iaddr2[16];
desc, sizeof(desc), int proto2;
0, 0, &timestamp, 0, 0) >= 0) { char desc[64];
syslog(LOG_DEBUG, "%d %d %hu->'%s':%hu '%s'", eport = 0; /* to indicate correct removing of port mapping */
index, proto2, eport2, iaddr2, iport2, desc); while(get_redirect_rule_by_index(index, 0,
if(0 == strcmp(iaddr2, senderaddrstr) &eport2, iaddr2, sizeof(iaddr2),
&& 0 == memcmp(desc, "NAT-PMP", 7)) { &iport2, &proto2,
desc, sizeof(desc),
0, 0, &timestamp, 0, 0) >= 0) {
syslog(LOG_DEBUG, "%d %d %hu->'%s':%hu '%s'",
index, proto2, eport2, iaddr2, iport2, desc);
if(0 == strcmp(iaddr2, senderaddrstr)
&& 0 == memcmp(desc, "NAT-PMP", 7)) {
/* (iport == 0) => remove all the mappings for this client */
if((iport == 0) || ((iport == iport2) && (proto == proto2))) {
r = _upnp_delete_redir(eport2, proto2); r = _upnp_delete_redir(eport2, proto2);
/* TODO : check return value */ if(r < 0) {
if(r<0) { syslog(LOG_ERR, "Failed to remove NAT-PMP mapping eport %hu, protocol %s",
syslog(LOG_ERR, "failed to remove port mapping"); eport2, (proto2==IPPROTO_TCP)?"TCP":"UDP");
index++; resp[3] = 2; /* Not Authorized/Refused */
break;
} else { } else {
syslog(LOG_INFO, "NAT-PMP %s port %hu mapping removed", syslog(LOG_INFO, "NAT-PMP %s port %hu mapping removed",
proto2==IPPROTO_TCP?"TCP":"UDP", eport2); proto2==IPPROTO_TCP?"TCP":"UDP", eport2);
@ -341,25 +348,15 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
index++; index++;
} }
} }
} else {
/* To improve the interworking between nat-pmp and
* UPnP, we should check that we remove only NAT-PMP
* mappings */
r = _upnp_delete_redir(eport, proto);
/*syslog(LOG_DEBUG, "%hu %d r=%d", eport, proto, r);*/
if(r<0) {
syslog(LOG_ERR, "Failed to remove NAT-PMP mapping eport %hu, protocol %s",
eport, (proto==IPPROTO_TCP)?"TCP":"UDP");
resp[3] = 2; /* Not Authorized/Refused */
}
} }
eport = 0; /* to indicate correct removing of port mapping */
} else if(iport==0) { } else if(iport==0) {
resp[3] = 2; /* Not Authorized/Refused */ resp[3] = 2; /* Not Authorized/Refused */
} else { /* iport > 0 && lifetime > 0 */ } else { /* iport > 0 && lifetime > 0 */
unsigned short eport_first = 0; unsigned short eport_first = 0;
int any_eport_allowed = 0; int any_eport_allowed = 0;
char desc[64]; char desc[64];
if(eport==0) /* if no suggested external port, use same a internal port */
eport = iport;
while(resp[3] == 0) { while(resp[3] == 0) {
if(eport_first == 0) { /* first time in loop */ if(eport_first == 0) { /* first time in loop */
eport_first = eport; eport_first = eport;