add update_portmapping() / update_portmapping_desc_timestamp() functions
This commit is contained in:
parent
34f80a011f
commit
bdac007771
|
@ -3,6 +3,7 @@ $Id: Changelog.txt,v 1.421 2016/02/12 12:34:37 nanard Exp $
|
|||
2016/02/12:
|
||||
return error 729 - ConflictWithOtherMechanisms if IGD v2 is enabled.
|
||||
add iptc_init() check in iptcrdr.c/init_redirect()
|
||||
add update_portmapping() / update_portmapping_desc_timestamp() functions
|
||||
|
||||
2016/02/11:
|
||||
use Linux libuuid uuid_generate() / BSD uuid_create() API
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id: commonrdr.h,v 1.9 2014/02/11 09:36:15 nanard Exp $ */
|
||||
/* $Id: commonrdr.h,v 1.10 2016/02/12 12:34:39 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* (c) 2006-2014 Thomas Bernard
|
||||
* (c) 2006-2016 Thomas Bernard
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
@ -52,5 +52,16 @@ unsigned short *
|
|||
get_portmappings_in_range(unsigned short startport, unsigned short endport,
|
||||
int proto, unsigned int * number);
|
||||
|
||||
#endif
|
||||
/* update the port mapping internal port, decription and timestamp */
|
||||
int
|
||||
update_portmapping(const char * ifname, unsigned short eport, int proto,
|
||||
unsigned short iport, const char * desc,
|
||||
unsigned int timestamp);
|
||||
|
||||
/* update the port mapping decription and timestamp */
|
||||
int
|
||||
update_portmapping_desc_timestamp(const char * ifname,
|
||||
unsigned short eport, int proto,
|
||||
const char * desc, unsigned int timestamp);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* $Id: ipfwrdr.c,v 1.12 2012/02/11 13:10:57 nanard Exp $ */
|
||||
/* $Id: ipfwrdr.c,v 1.16 2016/02/12 13:44:01 nanard Exp $ */
|
||||
/*
|
||||
* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2009 Jardel Weyrich
|
||||
* (c) 2011-2012 Thomas Bernard
|
||||
* (c) 2011-2016 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution
|
||||
*/
|
||||
|
@ -478,3 +478,71 @@ error:
|
|||
return array;
|
||||
}
|
||||
|
||||
int
|
||||
update_portmapping_desc_timestamp(const char * ifname,
|
||||
unsigned short eport, int proto,
|
||||
const char * desc, unsigned int timestamp)
|
||||
{
|
||||
UNUSED(ifname);
|
||||
del_desc_time(eport, proto);
|
||||
add_desc_time(eport, proto, desc, timestamp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
update_portmapping(const char * ifname, unsigned short eport, int proto,
|
||||
unsigned short iport, const char * desc,
|
||||
unsigned int timestamp)
|
||||
{
|
||||
int i, count_rules, total_rules = 0;
|
||||
struct ip_fw * rules = NULL;
|
||||
int r = -1;
|
||||
char iaddr[16];
|
||||
char rhost[16];
|
||||
int found;
|
||||
|
||||
if (ipfw_validate_protocol(proto) < 0)
|
||||
return -1;
|
||||
if (ipfw_validate_ifname(ifname) < 0)
|
||||
return -1;
|
||||
|
||||
do {
|
||||
count_rules = ipfw_fetch_ruleset(&rules, &total_rules, 10);
|
||||
if (count_rules < 0)
|
||||
goto error;
|
||||
} while (count_rules == 10);
|
||||
|
||||
found = 0;
|
||||
iaddr[0] = '\0';
|
||||
rhost[0] = '\0';
|
||||
|
||||
for (i=0; i<total_rules-1; i++) {
|
||||
const struct ip_fw const * ptr = &rules[i];
|
||||
if (proto == ptr->fw_prot && eport == ptr->fw_uar.fw_pts[0]) {
|
||||
if (inet_ntop(AF_INET, &ptr->fw_fwd_ip.sin_addr, iaddr, sizeof(iaddr)) == NULL) {
|
||||
syslog(LOG_ERR, "inet_ntop(): %m");
|
||||
goto error;
|
||||
}
|
||||
if ((ptr->fw_src.s_addr != 0) &&
|
||||
(inet_ntop(AF_INET, &ptr->fw_src.s_addr, rhost, sizeof(rhost)) == NULL)) {
|
||||
syslog(LOG_ERR, "inet_ntop(): %m");
|
||||
goto error;
|
||||
}
|
||||
found = 1;
|
||||
if (ipfw_exec(IP_FW_DEL, (struct ip_fw *)ptr, sizeof(*ptr)) < 0)
|
||||
goto error;
|
||||
del_desc_time(eport, proto);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ipfw_free_ruleset(&rules);
|
||||
rules = NULL;
|
||||
|
||||
if(found)
|
||||
r = add_redirect_rule2(ifname, rhost, eport, iaddr, iport, proto, desc, timestamp);
|
||||
|
||||
error:
|
||||
if (rules != NULL)
|
||||
ipfw_free_ruleset(&rules);
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -1552,6 +1552,249 @@ get_portmappings_in_range(unsigned short startport, unsigned short endport,
|
|||
return array;
|
||||
}
|
||||
|
||||
int
|
||||
update_portmapping_desc_timestamp(const char * ifname,
|
||||
unsigned short eport, int proto,
|
||||
const char * desc, unsigned int timestamp)
|
||||
{
|
||||
UNUSED(ifname);
|
||||
del_redirect_desc(eport, proto);
|
||||
add_redirect_desc(eport, proto, desc, timestamp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
update_rule_and_commit(const char * table, const char * chain,
|
||||
unsigned index, const struct ipt_entry * e)
|
||||
{
|
||||
IPTC_HANDLE h;
|
||||
int r = 0;
|
||||
|
||||
h = iptc_init(table);
|
||||
if(!h)
|
||||
{
|
||||
syslog(LOG_ERR, "%s() : iptc_init() failed : %s",
|
||||
"update_rule_and_commit", iptc_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
#ifdef IPTABLES_143
|
||||
if(!iptc_replace_entry(chain, e, index, h))
|
||||
#else
|
||||
if(!iptc_replace_entry(chain, e, index, &h))
|
||||
#endif
|
||||
{
|
||||
syslog(LOG_ERR, "%s(): iptc_replace_entry: %s",
|
||||
"update_rule_and_commit", iptc_strerror(errno));
|
||||
r = -1;
|
||||
}
|
||||
#ifdef IPTABLES_143
|
||||
else if(!iptc_commit(h))
|
||||
#else
|
||||
else if(!iptc_commit(&h))
|
||||
#endif
|
||||
{
|
||||
syslog(LOG_ERR, "%s(): iptc_commit: %s",
|
||||
"update_rule_and_commit", iptc_strerror(errno));
|
||||
r = -1;
|
||||
}
|
||||
#ifdef IPTABLES_143
|
||||
iptc_free(h);
|
||||
#else
|
||||
iptc_free(&h);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
update_portmapping(const char * ifname, unsigned short eport, int proto,
|
||||
unsigned short iport, const char * desc,
|
||||
unsigned int timestamp)
|
||||
{
|
||||
int r = 0;
|
||||
int found = 0;
|
||||
unsigned index = 0;
|
||||
unsigned i = 0;
|
||||
IPTC_HANDLE h;
|
||||
const struct ipt_entry * e;
|
||||
struct ipt_entry * new_e = NULL;
|
||||
size_t entry_len;
|
||||
const struct ipt_entry_target * target;
|
||||
struct ip_nat_multi_range * mr;
|
||||
const struct ipt_entry_match *match;
|
||||
uint32_t iaddr = 0;
|
||||
unsigned short old_iport;
|
||||
|
||||
h = iptc_init("nat");
|
||||
if(!h)
|
||||
{
|
||||
syslog(LOG_ERR, "%s() : iptc_init() failed : %s",
|
||||
"update_portmapping", iptc_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/* First step : find the right nat rule */
|
||||
if(!iptc_is_chain(miniupnpd_nat_chain, h))
|
||||
{
|
||||
syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain);
|
||||
r = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef IPTABLES_143
|
||||
for(e = iptc_first_rule(miniupnpd_nat_chain, h);
|
||||
e;
|
||||
e = iptc_next_rule(e, h), i++)
|
||||
#else
|
||||
for(e = iptc_first_rule(miniupnpd_nat_chain, &h);
|
||||
e;
|
||||
e = iptc_next_rule(e, &h), i++)
|
||||
#endif
|
||||
{
|
||||
if(proto==e->ip.proto)
|
||||
{
|
||||
match = (const struct ipt_entry_match *)&e->elems;
|
||||
if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))
|
||||
{
|
||||
const struct ipt_tcp * info;
|
||||
info = (const struct ipt_tcp *)match->data;
|
||||
if(eport != info->dpts[0])
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct ipt_udp * info;
|
||||
info = (const struct ipt_udp *)match->data;
|
||||
if(eport != info->dpts[0])
|
||||
continue;
|
||||
}
|
||||
/* we found the right rule */
|
||||
found = 1;
|
||||
index = i;
|
||||
target = (void *)e + e->target_offset;
|
||||
mr = (struct ip_nat_multi_range *)&target->data[0];
|
||||
iaddr = mr->range[0].min_ip;
|
||||
old_iport = ntohs(mr->range[0].min.all);
|
||||
entry_len = sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size;
|
||||
new_e = malloc(entry_len);
|
||||
if(new_e == NULL) {
|
||||
syslog(LOG_ERR, "%s: malloc(%u) error",
|
||||
"update_portmapping", (unsigned)entry_len);
|
||||
r = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(new_e, e, entry_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef IPTABLES_143
|
||||
iptc_free(h);
|
||||
#else
|
||||
iptc_free(&h);
|
||||
#endif
|
||||
if(!found || r < 0)
|
||||
return -1;
|
||||
syslog(LOG_INFO, "Trying to update nat rule at index %u", index);
|
||||
target = (void *)new_e + new_e->target_offset;
|
||||
mr = (struct ip_nat_multi_range *)&target->data[0];
|
||||
mr->range[0].min.all = mr->range[0].max.all = htons(iport);
|
||||
/* first update the nat rule */
|
||||
r = update_rule_and_commit("nat", miniupnpd_nat_chain, index, new_e);
|
||||
free(new_e); new_e = NULL;
|
||||
if(r < 0)
|
||||
return r;
|
||||
|
||||
/* update filter rule */
|
||||
h = iptc_init("filter");
|
||||
if(!h)
|
||||
{
|
||||
syslog(LOG_ERR, "%s() : iptc_init() failed : %s",
|
||||
"update_portmapping", iptc_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
i = 0; found = 0;
|
||||
if(!iptc_is_chain(miniupnpd_forward_chain, h))
|
||||
{
|
||||
syslog(LOG_ERR, "chain %s not found", miniupnpd_forward_chain);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we must find the right index for the filter rule */
|
||||
#ifdef IPTABLES_143
|
||||
for(e = iptc_first_rule(miniupnpd_forward_chain, h);
|
||||
e;
|
||||
e = iptc_next_rule(e, h), i++)
|
||||
#else
|
||||
for(e = iptc_first_rule(miniupnpd_forward_chain, &h);
|
||||
e;
|
||||
e = iptc_next_rule(e, &h), i++)
|
||||
#endif
|
||||
{
|
||||
if(proto!=e->ip.proto)
|
||||
continue;
|
||||
target = (void *)e + e->target_offset;
|
||||
match = (const struct ipt_entry_match *)&e->elems;
|
||||
if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))
|
||||
{
|
||||
const struct ipt_tcp * info;
|
||||
info = (const struct ipt_tcp *)match->data;
|
||||
if(old_iport != info->dpts[0])
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct ipt_udp * info;
|
||||
info = (const struct ipt_udp *)match->data;
|
||||
if(old_iport != info->dpts[0])
|
||||
continue;
|
||||
}
|
||||
if(iaddr != e->ip.dst.s_addr)
|
||||
continue;
|
||||
index = i;
|
||||
found = 1;
|
||||
entry_len = sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size;
|
||||
new_e = malloc(entry_len);
|
||||
if(new_e == NULL) {
|
||||
syslog(LOG_ERR, "%s: malloc(%u) error",
|
||||
"update_portmapping", (unsigned)entry_len);
|
||||
r = -1;
|
||||
} else {
|
||||
memcpy(new_e, e, entry_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef IPTABLES_143
|
||||
iptc_free(h);
|
||||
#else
|
||||
iptc_free(&h);
|
||||
#endif
|
||||
if(!found || r < 0)
|
||||
return -1;
|
||||
|
||||
syslog(LOG_INFO, "Trying to update filter rule at index %u", index);
|
||||
match = (struct ipt_entry_match *)&new_e->elems;
|
||||
if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))
|
||||
{
|
||||
struct ipt_tcp * info;
|
||||
info = (struct ipt_tcp *)match->data;
|
||||
info->dpts[0] = info->dpts[1] = iport;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ipt_udp * info;
|
||||
info = (struct ipt_udp *)match->data;
|
||||
info->dpts[0] = info->dpts[1] = iport;
|
||||
}
|
||||
r = update_rule_and_commit("filter", miniupnpd_forward_chain, index, new_e);
|
||||
free(new_e); new_e = NULL;
|
||||
if(r < 0)
|
||||
return r;
|
||||
|
||||
return update_portmapping_desc_timestamp(ifname, eport, proto, desc, timestamp);
|
||||
}
|
||||
|
||||
/* ================================ */
|
||||
#ifdef DEBUG
|
||||
static int
|
||||
|
|
|
@ -53,6 +53,8 @@ main(int argc, char ** argv)
|
|||
fprintf(stderr, "addpeenatrule failed\n");
|
||||
}
|
||||
#endif
|
||||
/*update_portmapping_desc_timestamp(NULL, eport, proto, "updated desc", time(NULL)+42);*/
|
||||
update_portmapping(NULL, eport, proto, iport+1, "updated rule", time(NULL)+42);
|
||||
/* test */
|
||||
{
|
||||
unsigned short p1, p2;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Id: obsdrdr.c,v 1.84 2015/02/08 08:55:55 nanard Exp $ */
|
||||
/* $Id: obsdrdr.c,v 1.86 2016/02/12 13:11:03 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2015 Thomas Bernard
|
||||
* (c) 2006-2016 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
|
@ -607,7 +607,7 @@ error:
|
|||
static int
|
||||
priv_delete_redirect_rule(const char * ifname, unsigned short eport,
|
||||
int proto, unsigned short * iport,
|
||||
in_addr_t * iaddr)
|
||||
in_addr_t * iaddr, char * rhost, int rhostlen)
|
||||
{
|
||||
int i, n;
|
||||
struct pfioc_rule pr;
|
||||
|
@ -683,6 +683,14 @@ priv_delete_redirect_rule(const char * ifname, unsigned short eport,
|
|||
*iaddr = pr.rule.rdr.addr.v.a.addr.v4.s_addr;
|
||||
}
|
||||
#endif
|
||||
if(rhost && rhostlen > 0)
|
||||
{
|
||||
if (pr.rule.src.addr.v.a.addr.v4.s_addr == 0)
|
||||
rhost[0] = '\0'; /* empty string */
|
||||
else
|
||||
inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr,
|
||||
rhost, rhostlen);
|
||||
}
|
||||
pr.action = PF_CHANGE_GET_TICKET;
|
||||
if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
|
||||
{
|
||||
|
@ -708,7 +716,7 @@ int
|
|||
delete_redirect_rule(const char * ifname, unsigned short eport,
|
||||
int proto)
|
||||
{
|
||||
return priv_delete_redirect_rule(ifname, eport, proto, NULL, NULL);
|
||||
return priv_delete_redirect_rule(ifname, eport, proto, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -782,7 +790,7 @@ delete_redirect_and_filter_rules(const char * ifname, unsigned short eport,
|
|||
int r;
|
||||
unsigned short iport;
|
||||
in_addr_t iaddr;
|
||||
r = priv_delete_redirect_rule(ifname, eport, proto, &iport, &iaddr);
|
||||
r = priv_delete_redirect_rule(ifname, eport, proto, &iport, &iaddr, NULL, 0);
|
||||
if(r == 0)
|
||||
{
|
||||
r = priv_delete_filter_rule(ifname, iport, proto, iaddr);
|
||||
|
@ -978,6 +986,61 @@ get_portmappings_in_range(unsigned short startport, unsigned short endport,
|
|||
return array;
|
||||
}
|
||||
|
||||
/* update the port mapping internal port, decription and timestamp */
|
||||
int
|
||||
update_portmapping(const char * ifname, unsigned short eport, int proto,
|
||||
unsigned short iport, const char * desc,
|
||||
unsigned int timestamp)
|
||||
{
|
||||
unsigned short old_iport;
|
||||
in_addr_t iaddr;
|
||||
char iaddr_str[16];
|
||||
char rhost[32];
|
||||
|
||||
if(priv_delete_redirect_rule(ifname, eport, proto, &old_iport, &iaddr, rhost, sizeof(rhost)) < 0)
|
||||
return -1;
|
||||
if (priv_delete_filter_rule(ifname, old_iport, proto, iaddr) < 0)
|
||||
return -1;
|
||||
|
||||
inet_ntop(AF_INET, &iaddr, iaddr_str, sizeof(iaddr_str));
|
||||
|
||||
if(add_redirect_rule2(ifname, rhost, eport, iaddr_str, iport, proto,
|
||||
desc, timestamp) < 0)
|
||||
return -1;
|
||||
if(add_filter_rule2(ifname, rhost, iaddr_str, eport, iport, proto, desc) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* update the port mapping decription and timestamp */
|
||||
int
|
||||
update_portmapping_desc_timestamp(const char * ifname,
|
||||
unsigned short eport, int proto,
|
||||
const char * desc, unsigned int timestamp)
|
||||
{
|
||||
unsigned short iport;
|
||||
in_addr_t iaddr;
|
||||
char iaddr_str[16];
|
||||
char rhost[32];
|
||||
|
||||
if(priv_delete_redirect_rule(ifname, eport, proto, &iport, &iaddr, rhost, sizeof(rhost)) < 0)
|
||||
return -1;
|
||||
if (priv_delete_filter_rule(ifname, iport, proto, iaddr) < 0)
|
||||
return -1;
|
||||
|
||||
inet_ntop(AF_INET, &iaddr, iaddr_str, sizeof(iaddr_str));
|
||||
|
||||
if(add_redirect_rule2(ifname, rhost, eport, iaddr_str, iport, proto,
|
||||
desc, timestamp) < 0)
|
||||
return -1;
|
||||
if(add_filter_rule2(ifname, rhost, iaddr_str, eport, iport, proto, desc) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* this function is only for testing */
|
||||
#if TEST
|
||||
void
|
||||
|
|
|
@ -264,6 +264,7 @@ upnp_redirect(const char * rhost, unsigned short eport,
|
|||
{
|
||||
int proto, r;
|
||||
char iaddr_old[32];
|
||||
char rhost_old[32];
|
||||
unsigned short iport_old;
|
||||
struct in_addr address;
|
||||
unsigned int timestamp;
|
||||
|
@ -280,20 +281,59 @@ upnp_redirect(const char * rhost, unsigned short eport,
|
|||
"%hu->%s:%hu %s", eport, iaddr, iport, protocol);
|
||||
return -3;
|
||||
}
|
||||
/* IGDv1 (WANIPConnection:1 Service Template Version 1.01 / Nov 12, 2001)
|
||||
* - 2.2.20.PortMappingDescription :
|
||||
* Overwriting Previous / Existing Port Mappings:
|
||||
* If the RemoteHost, ExternalPort, PortMappingProtocol and InternalClient
|
||||
* are exactly the same as an existing mapping, the existing mapping values
|
||||
* for InternalPort, PortMappingDescription, PortMappingEnabled and
|
||||
* PortMappingLeaseDuration are overwritten.
|
||||
* Rejecting a New Port Mapping:
|
||||
* In cases where the RemoteHost, ExternalPort and PortMappingProtocol
|
||||
* are the same as an existing mapping, but the InternalClient is
|
||||
* different, the action is rejected with an appropriate error.
|
||||
* Add or Reject New Port Mapping behavior based on vendor implementation:
|
||||
* In cases where the ExternalPort, PortMappingProtocol and InternalClient
|
||||
* are the same, but RemoteHost is different, the vendor can choose to
|
||||
* support both mappings simultaneously, or reject the second mapping
|
||||
* with an appropriate error.
|
||||
*
|
||||
* - 2.4.16.AddPortMapping
|
||||
* This action creates a new port mapping or overwrites an existing
|
||||
* mapping with the same internal client. If the ExternalPort and
|
||||
* PortMappingProtocol pair is already mapped to another internal client,
|
||||
* an error is returned.
|
||||
*
|
||||
* IGDv2 (WANIPConnection:2 Service Standardized DCP (SDCP) Sep 10, 2010)
|
||||
* Protocol ExternalPort RemoteHost InternalClient Result
|
||||
* = = ≠ ≠ Failure
|
||||
* = = ≠ = Failure or success
|
||||
* (vendor specific)
|
||||
* = = = ≠ Failure
|
||||
* = = = = Success (overwrite)
|
||||
*/
|
||||
rhost_old[0] = '\0';
|
||||
r = get_redirect_rule(ext_if_name, eport, proto,
|
||||
iaddr_old, sizeof(iaddr_old), &iport_old, 0, 0,
|
||||
0, 0,
|
||||
rhost_old, sizeof(rhost_old),
|
||||
×tamp, 0, 0);
|
||||
if(r == 0) {
|
||||
/* if existing redirect rule matches redirect request return success
|
||||
* xbox 360 does not keep track of the port it redirects and will
|
||||
* redirect another port when receiving ConflictInMappingEntry */
|
||||
if(strcmp(iaddr, iaddr_old)==0 && iport==iport_old) {
|
||||
syslog(LOG_INFO, "ignoring redirect request as it matches existing redirect");
|
||||
if(strcmp(iaddr, iaddr_old)==0 &&
|
||||
((rhost == NULL && rhost_old[0]=='\0') ||
|
||||
(rhost && (strcmp(rhost, "*") == 0) && rhost_old[0]=='\0') ||
|
||||
(rhost && (strcmp(rhost, rhost_old) == 0)))) {
|
||||
syslog(LOG_INFO, "updating existing port mapping %hu %s (rhost '%s') => %s:%hu",
|
||||
eport, protocol, rhost_old, iaddr_old, iport_old);
|
||||
timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0;
|
||||
/* TODO : update lease file */
|
||||
if(iport != iport_old) {
|
||||
return update_portmapping(ext_if_name, eport, proto, iport, desc, timestamp);
|
||||
} else {
|
||||
return update_portmapping_desc_timestamp(ext_if_name, eport, proto, desc, timestamp);
|
||||
}
|
||||
} else {
|
||||
|
||||
syslog(LOG_INFO, "port %hu protocol %s already redirected to %s:%hu",
|
||||
eport, protocol, iaddr_old, iport_old);
|
||||
syslog(LOG_INFO, "port %hu %s (rhost '%s') already redirected to %s:%hu",
|
||||
eport, protocol, rhost_old, iaddr_old, iport_old);
|
||||
return -2;
|
||||
}
|
||||
#ifdef CHECK_PORTINUSE
|
||||
|
@ -309,8 +349,6 @@ upnp_redirect(const char * rhost, unsigned short eport,
|
|||
return upnp_redirect_internal(rhost, eport, iaddr, iport, proto,
|
||||
desc, timestamp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -445,14 +445,6 @@ AddPortMapping(struct upnphttp * h, const char * action, const char * ns)
|
|||
action, eport, int_ip, iport, protocol, desc, leaseduration,
|
||||
r_host ? r_host : "NULL");
|
||||
|
||||
/* TODO : be compliant with IGD spec for updating existing port mappings.
|
||||
See "WANIPConnection:1 Service Template Version 1.01" 2.2.20.PortMappingDescription :
|
||||
Overwriting Previous / Existing Port Mappings:
|
||||
If the RemoteHost, ExternalPort, PortMappingProtocol and InternalClient are
|
||||
exactly the same as an existing mapping, the existing mapping values for InternalPort,
|
||||
PortMappingDescription, PortMappingEnabled and PortMappingLeaseDuration are
|
||||
overwritten.
|
||||
*/
|
||||
r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration);
|
||||
|
||||
ClearNameValueList(&data);
|
||||
|
|
Loading…
Reference in New Issue