PCP: check pinhole before adding in CreatePCPMap_FW()

fixes #188
This commit is contained in:
Thomas Bernard 2016-01-18 20:16:06 +01:00
parent 3dfbeccee9
commit e252acef88
5 changed files with 96 additions and 15 deletions

View File

@ -1,7 +1,7 @@
/* $Id: iptpinhole.c,v 1.14 2015/02/10 15:01:03 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2012-2015 Thomas Bernard
* (c) 2012-2016 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -13,6 +13,7 @@
#include <sys/queue.h>
#include "../config.h"
#include "../macros.h"
#include "iptpinhole.h"
#include "../upnpglobalvars.h"
@ -262,6 +263,37 @@ int add_pinhole(const char * ifname,
return uid;
}
int
find_pinhole(const char * ifname,
const char * rem_host, unsigned short rem_port,
const char * int_client, unsigned short int_port,
int proto,
char *desc, int desc_len, unsigned int * timestamp)
{
struct pinhole_t * p;
struct in6_addr saddr;
struct in6_addr daddr;
UNUSED(ifname);
if(rem_host && (rem_host[0] != '\0')) {
inet_pton(AF_INET6, rem_host, &saddr);
} else {
memset(&saddr, 0, sizeof(struct in6_addr));
}
inet_pton(AF_INET6, int_client, &daddr);
for(p = pinhole_list.lh_first; p != NULL; p = p->entries.le_next) {
if((proto == p->proto) && (rem_port == p->sport) &&
(0 == memcmp(&saddr, &p->saddr, sizeof(struct in6_addr))) &&
(int_port == p->dport) &&
(0 == memcmp(&daddr, &p->daddr, sizeof(struct in6_addr)))) {
if(desc) strncpy(desc, p->desc, desc_len);
if(timestamp) *timestamp = p->timestamp;
return (int)p->uid;
}
}
return -1; /* not found */
}
int
delete_pinhole(unsigned short uid)
{

View File

@ -1,7 +1,7 @@
/* $Id: iptpinhole.h,v 1.5 2012/05/08 20:41:45 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2012 Thomas Bernard
* (c) 2012-2016 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef IPTPINHOLE_H_INCLUDED
@ -10,6 +10,12 @@
#ifdef ENABLE_UPNPPINHOLE
#include <sys/types.h>
int find_pinhole(const char * ifname,
const char * rem_host, unsigned short rem_port,
const char * int_client, unsigned short int_port,
int proto,
char *desc, int desc_len, unsigned int * timestamp);
int add_pinhole(const char * ifname,
const char * rem_host, unsigned short rem_port,
const char * int_client, unsigned short int_port,

View File

@ -989,17 +989,34 @@ static int CreatePCPMap_FW(pcp_info_t *pcp_msg_info)
{
#ifdef ENABLE_UPNPPINHOLE
int uid;
int r = upnp_add_inboundpinhole(NULL, 0,
int r;
/* first check if pinhole already exists */
uid = upnp_find_inboundpinhole(NULL, 0,
pcp_msg_info->mapped_str,
pcp_msg_info->int_port,
pcp_msg_info->protocol,
pcp_msg_info->desc,
pcp_msg_info->lifetime,
&uid);
if (r < 0)
return PCP_ERR_NO_RESOURCES;
pcp_msg_info->ext_port = pcp_msg_info->int_port;
return PCP_SUCCESS;
NULL, 0, /* desc */
NULL /* lifetime */);
if(uid >= 0) {
/* pinhole already exists, updating */
syslog(LOG_INFO, "updating pinhole to %s:%hu %s",
pcp_msg_info->mapped_str, pcp_msg_info->int_port,
(pcp_msg_info->protocol == IPPROTO_TCP)?"TCP":"UDP");
r = upnp_update_inboundpinhole((unsigned short)uid, pcp_msg_info->lifetime);
return r >= 0 ? PCP_SUCCESS : PCP_ERR_NO_RESOURCES;
} else {
r = upnp_add_inboundpinhole(NULL, 0,
pcp_msg_info->mapped_str,
pcp_msg_info->int_port,
pcp_msg_info->protocol,
pcp_msg_info->desc,
pcp_msg_info->lifetime,
&uid);
if (r < 0)
return PCP_ERR_NO_RESOURCES;
pcp_msg_info->ext_port = pcp_msg_info->int_port;
return PCP_SUCCESS;
}
#else
UNUSED(pcp_msg_info);
return PCP_ERR_NO_RESOURCES;

View File

@ -1,7 +1,7 @@
/* $Id: upnppinhole.c,v 1.7 2014/12/09 09:13:53 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2016 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -87,6 +87,21 @@ upnp_check_outbound_pinhole(int proto, int * timeout)
}
#endif
int
upnp_find_inboundpinhole(const char * raddr, unsigned short rport,
const char * iaddr, unsigned short iport,
int proto, char * desc, int desc_len, unsigned int * leasetime)
{
#if defined(USE_PF) || defined(USE_NETFILTER)
int uid;
uid = find_pinhole(NULL, raddr, rport, iaddr, iport, proto,
desc, desc_len, leasetime);
return uid;
#else
return -42;
#endif
}
/* upnp_add_inboundpinhole()
* returns: 1 on success
* -1 Pinhole space exhausted

View File

@ -1,7 +1,8 @@
/* $Id: upnppinhole.h,v 1.2 2012/09/18 08:29:49 nanard Exp $ */
/* MiniUPnP project
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2016 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -12,7 +13,8 @@
#ifdef ENABLE_UPNPPINHOLE
/* functions to be used by WANIPv6_FirewallControl implementation */
/* functions to be used by WANIPv6_FirewallControl implementation
* and PCP (IPv6) */
#if 0
/* retrieve outbound pinhole timeout */
@ -20,6 +22,15 @@ int
upnp_check_outbound_pinhole(int proto, int * timeout);
#endif
/* find an inbound pinhole base on remove host:port / local host:port
* return the (positive) uid or a negative value if not found */
int
upnp_find_inboundpinhole(const char * raddr, unsigned short rport,
const char * iaddr, unsigned short iport,
int proto,
char * desc, int desc_len, unsigned int * leasetime);
/* add an inbound pinehole
* return value :
* 1 = success
@ -31,7 +42,7 @@ upnp_add_inboundpinhole(const char * raddr, unsigned short rport,
int proto, char * desc,
unsigned int leasetime, int * uid);
/*
/* get from uid
* return values :
* -1 not found
* */