miniupnpd: detect port in use / already forwarded
Patch submitted by David Kerr
This commit is contained in:
parent
d9f265d0cc
commit
013b0df388
1
README
1
README
|
@ -40,4 +40,5 @@ Thanks to :
|
||||||
* Alexey Osipov
|
* Alexey Osipov
|
||||||
* Alexey Kuznetsov
|
* Alexey Kuznetsov
|
||||||
* Chiaki Ishikawa
|
* Chiaki Ishikawa
|
||||||
|
* David Kerr
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
$Id: Changelog.txt,v 1.292 2012/06/29 19:26:07 nanard Exp $
|
$Id: Changelog.txt,v 1.292 2012/06/29 19:26:07 nanard Exp $
|
||||||
|
|
||||||
|
2012/07/10:
|
||||||
|
Detect port in use - patch by David Kerr
|
||||||
|
|
||||||
2012/06/29:
|
2012/06/29:
|
||||||
added DISABLE_CONFIG_FILE in options.h to disable miniupnpd.conf parsing
|
added DISABLE_CONFIG_FILE in options.h to disable miniupnpd.conf parsing
|
||||||
Add command line parsing for clean_ruleset_interval option
|
Add command line parsing for clean_ruleset_interval option
|
||||||
|
|
|
@ -41,7 +41,7 @@ SBININSTALLDIR = $(INSTALLPREFIX)/sbin
|
||||||
ETCINSTALLDIR = $(PREFIX)/etc/miniupnpd
|
ETCINSTALLDIR = $(PREFIX)/etc/miniupnpd
|
||||||
|
|
||||||
BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
|
BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
|
||||||
upnpreplyparse.o minixml.o \
|
upnpreplyparse.o minixml.o portinuse.o \
|
||||||
upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \
|
upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \
|
||||||
options.o upnppermissions.o minissdp.o natpmp.o \
|
options.o upnppermissions.o minissdp.o natpmp.o \
|
||||||
upnpevents.o upnputils.o getconnstatus.o \
|
upnpevents.o upnputils.o getconnstatus.o \
|
||||||
|
@ -196,14 +196,16 @@ upnpsoap.o: upnpredirect.h upnppinhole.h getifaddr.h getifstats.h
|
||||||
upnpsoap.o: getconnstatus.h upnpurns.h
|
upnpsoap.o: getconnstatus.h upnpurns.h
|
||||||
upnpreplyparse.o: upnpreplyparse.h minixml.h
|
upnpreplyparse.o: upnpreplyparse.h minixml.h
|
||||||
minixml.o: minixml.h
|
minixml.o: minixml.h
|
||||||
|
portinuse.o: macros.h config.h upnpglobalvars.h upnppermissions.h
|
||||||
|
portinuse.o: miniupnpdtypes.h getifaddr.h portinuse.h
|
||||||
upnpredirect.o: macros.h config.h upnpredirect.h upnpglobalvars.h
|
upnpredirect.o: macros.h config.h upnpredirect.h upnpglobalvars.h
|
||||||
upnpredirect.o: upnppermissions.h miniupnpdtypes.h upnpevents.h
|
upnpredirect.o: upnppermissions.h miniupnpdtypes.h upnpevents.h portinuse.h
|
||||||
upnpredirect.o: netfilter/iptcrdr.h commonrdr.h
|
upnpredirect.o: netfilter/iptcrdr.h commonrdr.h
|
||||||
getifaddr.o: config.h getifaddr.h
|
getifaddr.o: config.h getifaddr.h
|
||||||
daemonize.o: daemonize.h config.h
|
daemonize.o: daemonize.h config.h
|
||||||
upnpglobalvars.o: config.h upnpglobalvars.h upnppermissions.h
|
upnpglobalvars.o: config.h upnpglobalvars.h upnppermissions.h
|
||||||
upnpglobalvars.o: miniupnpdtypes.h
|
upnpglobalvars.o: miniupnpdtypes.h
|
||||||
options.o: options.h config.h upnppermissions.h upnpglobalvars.h
|
options.o: config.h options.h upnppermissions.h upnpglobalvars.h
|
||||||
options.o: miniupnpdtypes.h
|
options.o: miniupnpdtypes.h
|
||||||
upnppermissions.o: config.h upnppermissions.h
|
upnppermissions.o: config.h upnppermissions.h
|
||||||
minissdp.o: config.h upnpdescstrings.h miniupnpdpath.h upnphttp.h
|
minissdp.o: config.h upnpdescstrings.h miniupnpdpath.h upnphttp.h
|
||||||
|
@ -211,6 +213,7 @@ minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h
|
||||||
minissdp.o: upnputils.h getroute.h codelength.h
|
minissdp.o: upnputils.h getroute.h codelength.h
|
||||||
natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h
|
natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h
|
||||||
natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h
|
natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h
|
||||||
|
natpmp.o: portinuse.h
|
||||||
upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h
|
upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h
|
||||||
upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h
|
upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h
|
||||||
upnputils.o: config.h upnputils.h
|
upnputils.o: config.h upnputils.h
|
||||||
|
@ -228,7 +231,6 @@ netfilter/iptcrdr.o: config.h upnpglobalvars.h upnppermissions.h
|
||||||
netfilter/iptcrdr.o: miniupnpdtypes.h
|
netfilter/iptcrdr.o: miniupnpdtypes.h
|
||||||
netfilter/iptpinhole.o: config.h netfilter/iptpinhole.h upnpglobalvars.h
|
netfilter/iptpinhole.o: config.h netfilter/iptpinhole.h upnpglobalvars.h
|
||||||
netfilter/iptpinhole.o: upnppermissions.h config.h miniupnpdtypes.h
|
netfilter/iptpinhole.o: upnppermissions.h config.h miniupnpdtypes.h
|
||||||
netfilter/iptpinhole.o: netfilter/tiny_nf_nat.h
|
|
||||||
testupnpdescgen.o: macros.h config.h upnpdescgen.h
|
testupnpdescgen.o: macros.h config.h upnpdescgen.h
|
||||||
upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h
|
upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h
|
||||||
upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h
|
upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h
|
||||||
|
|
|
@ -23,9 +23,11 @@
|
||||||
#include "upnpredirect.h"
|
#include "upnpredirect.h"
|
||||||
#include "commonrdr.h"
|
#include "commonrdr.h"
|
||||||
#include "upnputils.h"
|
#include "upnputils.h"
|
||||||
|
#include "portinuse.h"
|
||||||
|
|
||||||
#ifdef ENABLE_NATPMP
|
#ifdef ENABLE_NATPMP
|
||||||
|
|
||||||
|
|
||||||
int OpenAndConfNATPMPSocket(in_addr_t addr)
|
int OpenAndConfNATPMPSocket(in_addr_t addr)
|
||||||
{
|
{
|
||||||
int snatpmp;
|
int snatpmp;
|
||||||
|
@ -267,6 +269,12 @@ void ProcessIncomingNATPMPPacket(int s)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (port_in_use(ext_if_name, eport, proto, senderaddrstr, iport)) {
|
||||||
|
syslog(LOG_INFO, "port %hu protocol %s already in use", eport, (proto==IPPROTO_TCP)?"tcp":"udp");
|
||||||
|
eport++;
|
||||||
|
r = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
{ /* do the redirection */
|
{ /* do the redirection */
|
||||||
char desc[64];
|
char desc[64];
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -237,6 +237,18 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
|
||||||
char * rhost, int rhostlen,
|
char * rhost, int rhostlen,
|
||||||
unsigned int * timestamp,
|
unsigned int * timestamp,
|
||||||
u_int64_t * packets, u_int64_t * bytes)
|
u_int64_t * packets, u_int64_t * bytes)
|
||||||
|
{
|
||||||
|
return get_nat_redirect_rule(miniupnpd_nat_chain, ifname, eport, proto, iaddr, iaddrlen, iport,
|
||||||
|
desc, desclen, rhost, rhostlen,timestamp, packets, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_nat_redirect_rule(const char * nat_chain_name, const char * ifname, unsigned short eport, int proto,
|
||||||
|
char * iaddr, int iaddrlen, unsigned short * iport,
|
||||||
|
char * desc, int desclen,
|
||||||
|
char * rhost, int rhostlen,
|
||||||
|
unsigned int * timestamp,
|
||||||
|
u_int64_t * packets, u_int64_t * bytes)
|
||||||
{
|
{
|
||||||
int r = -1;
|
int r = -1;
|
||||||
IPTC_HANDLE h;
|
IPTC_HANDLE h;
|
||||||
|
@ -254,18 +266,18 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
|
||||||
iptc_strerror(errno));
|
iptc_strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(!iptc_is_chain(miniupnpd_nat_chain, h))
|
if(!iptc_is_chain(nat_chain_name, h))
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain);
|
syslog(LOG_ERR, "chain %s not found", nat_chain_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef IPTABLES_143
|
#ifdef IPTABLES_143
|
||||||
for(e = iptc_first_rule(miniupnpd_nat_chain, h);
|
for(e = iptc_first_rule(nat_chain_name, h);
|
||||||
e;
|
e;
|
||||||
e = iptc_next_rule(e, h))
|
e = iptc_next_rule(e, h))
|
||||||
#else
|
#else
|
||||||
for(e = iptc_first_rule(miniupnpd_nat_chain, &h);
|
for(e = iptc_first_rule(nat_chain_name, &h);
|
||||||
e;
|
e;
|
||||||
e = iptc_next_rule(e, &h))
|
e = iptc_next_rule(e, &h))
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,6 +25,14 @@ add_filter_rule2(const char * ifname,
|
||||||
int
|
int
|
||||||
delete_redirect_and_filter_rules(unsigned short eport, int proto);
|
delete_redirect_and_filter_rules(unsigned short eport, int proto);
|
||||||
|
|
||||||
|
int
|
||||||
|
get_nat_redirect_rule(const char * nat_chain_name, const char * ifname, unsigned short eport, int proto,
|
||||||
|
char * iaddr, int iaddrlen, unsigned short * iport,
|
||||||
|
char * desc, int desclen,
|
||||||
|
char * rhost, int rhostlen,
|
||||||
|
unsigned int * timestamp,
|
||||||
|
u_int64_t * packets, u_int64_t * bytes);
|
||||||
|
|
||||||
/* for debug */
|
/* for debug */
|
||||||
int
|
int
|
||||||
list_redirect_rule(const char * ifname);
|
list_redirect_rule(const char * ifname);
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
/* */
|
||||||
|
/* MiniUPnP project
|
||||||
|
* (c) 2007-2012 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 */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "macros.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "upnpglobalvars.h"
|
||||||
|
#include "getifaddr.h"
|
||||||
|
#include "portinuse.h"
|
||||||
|
|
||||||
|
/* Hardcoded for now. Ideally would come from .conf file */
|
||||||
|
char *chains_to_check[] = { "PREROUTING" , 0 };
|
||||||
|
|
||||||
|
int port_in_use(const char *if_name, unsigned eport, int proto, const char *iaddr, unsigned iport)
|
||||||
|
{
|
||||||
|
char line[256];
|
||||||
|
FILE *f;
|
||||||
|
int found = 0;
|
||||||
|
char ip_addr_str[INET_ADDRSTRLEN];
|
||||||
|
struct in_addr ip_addr = { .s_addr = 0 };
|
||||||
|
const char tcpfile[] = "/proc/net/tcp";
|
||||||
|
const char udpfile[] = "/proc/net/udp";
|
||||||
|
|
||||||
|
f = fopen((proto==IPPROTO_TCP)?tcpfile:udpfile, "r");
|
||||||
|
if (!f) return 0;
|
||||||
|
|
||||||
|
if(getifaddr(if_name, ip_addr_str, INET_ADDRSTRLEN) == 0)
|
||||||
|
ip_addr.s_addr = inet_addr(ip_addr_str);
|
||||||
|
|
||||||
|
syslog(LOG_DEBUG, "Check protocol %s for port %d on ext_if %s %s, %8X",
|
||||||
|
(proto==IPPROTO_TCP)?"tcp":"udp", eport, if_name, ip_addr_str, (unsigned)ip_addr.s_addr);
|
||||||
|
|
||||||
|
while (fgets(line, 255, f)) {
|
||||||
|
char eaddr[68];
|
||||||
|
unsigned tmp_port;
|
||||||
|
if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
|
||||||
|
"%*x:%*x %*x %*d %*d %*llu",
|
||||||
|
eaddr, &tmp_port) == 2
|
||||||
|
) {
|
||||||
|
/* TODO add IPV6 support if enabled
|
||||||
|
* Presently assumes IPV4 */
|
||||||
|
// syslog(LOG_DEBUG, "port_in_use check port %d and address %s", tmp_port, eaddr);
|
||||||
|
if (tmp_port == eport) {
|
||||||
|
char tmp_addr[4];
|
||||||
|
struct in_addr *tmp_ip_addr = (struct in_addr *)tmp_addr;
|
||||||
|
if (sscanf(eaddr,"%2hhx%2hhx%2hhx%2hhx",
|
||||||
|
&tmp_addr[3],&tmp_addr[2],&tmp_addr[1],&tmp_addr[0]) == 4)
|
||||||
|
{
|
||||||
|
if (tmp_ip_addr->s_addr == 0 || tmp_ip_addr->s_addr == ip_addr.s_addr)
|
||||||
|
{
|
||||||
|
found++;
|
||||||
|
break; /* don't care how many, just that we found at least one */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
char iaddr_old[16];
|
||||||
|
unsigned short iport_old;
|
||||||
|
int i = 0;
|
||||||
|
while (chains_to_check[i]) {
|
||||||
|
if (get_nat_redirect_rule(chains_to_check[i], if_name, eport, proto,
|
||||||
|
iaddr_old, sizeof(iaddr_old),&iport_old,
|
||||||
|
0, 0, 0, 0, 0, 0, 0) == 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_DEBUG, "port_in_use check port %d on nat chain %s redirected to %s port %d", eport,
|
||||||
|
chains_to_check[i], iaddr_old, iport_old);
|
||||||
|
if (!(strcmp(iaddr, iaddr_old)==0 && iport==iport_old)) {
|
||||||
|
/* only "in use" if redirected to somewhere else */
|
||||||
|
found++;
|
||||||
|
break; /* don't care how many, just that we found at least one */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* */
|
||||||
|
/* MiniUPnP project
|
||||||
|
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||||
|
* (c) 2006-2011 Thomas Bernard
|
||||||
|
* This software is subject to the conditions detailed
|
||||||
|
* in the LICENCE file provided within the distribution */
|
||||||
|
|
||||||
|
#ifndef __PORTINUSE_H__
|
||||||
|
#define __PORTINUSE_H__
|
||||||
|
|
||||||
|
/* portinuse()
|
||||||
|
* determine wither a port is already in use
|
||||||
|
* on a given interface.
|
||||||
|
* returns: 0 not in use, 1 in use */
|
||||||
|
int
|
||||||
|
port_in_use(const char *if_name, unsigned port, int proto, const char *iaddr, unsigned iport);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "upnpredirect.h"
|
#include "upnpredirect.h"
|
||||||
#include "upnpglobalvars.h"
|
#include "upnpglobalvars.h"
|
||||||
#include "upnpevents.h"
|
#include "upnpevents.h"
|
||||||
|
#include "portinuse.h"
|
||||||
#if defined(USE_NETFILTER)
|
#if defined(USE_NETFILTER)
|
||||||
#include "netfilter/iptcrdr.h"
|
#include "netfilter/iptcrdr.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -294,6 +295,10 @@ upnp_redirect(const char * rhost, unsigned short eport,
|
||||||
eport, protocol, iaddr_old, iport_old);
|
eport, protocol, iaddr_old, iport_old);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (port_in_use(ext_if_name, eport, proto, iaddr, iport)) {
|
||||||
|
syslog(LOG_INFO, "port %hu protocol %s already in use", eport, protocol);
|
||||||
|
return -2;
|
||||||
} else {
|
} else {
|
||||||
timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0;
|
timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0;
|
||||||
syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
|
syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
|
||||||
|
|
Loading…
Reference in New Issue