Merge branch 'portinuse'
Conflicts: miniupnpd/Makefile.linux
This commit is contained in:
commit
08127b85d4
1
README
1
README
|
@ -40,6 +40,7 @@ Thanks to :
|
|||
* Alexey Osipov
|
||||
* Alexey Kuznetsov
|
||||
* Chiaki Ishikawa
|
||||
* David Kerr
|
||||
* Jardel Weyrich
|
||||
* Leah X. Schmidt
|
||||
* Peter Tatrai
|
||||
|
|
|
@ -10,6 +10,7 @@ testupnpdescgen
|
|||
testupnppermissions
|
||||
testgetroute
|
||||
testasyncsendto
|
||||
testportinuse
|
||||
netfilter/testiptcrdr
|
||||
netfilter/testiptcrdr_dscp
|
||||
netfilter/testiptcrdr_peer
|
||||
|
|
|
@ -185,6 +185,9 @@ VERSION 1.8 : released on 2013/02/06
|
|||
2012/07/14:
|
||||
Add -z command line option to change friendly name (thanks to Shawn Fisher)
|
||||
|
||||
2012/07/10:
|
||||
Detect port in use - patch by David Kerr
|
||||
|
||||
2012/06/29:
|
||||
added DISABLE_CONFIG_FILE in options.h to disable miniupnpd.conf parsing
|
||||
Add command line parsing for clean_ruleset_interval option
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile,v 1.76 2014/03/10 10:26:15 nanard Exp $
|
||||
# $Id: Makefile,v 1.76.2.2 2014/03/14 10:49:08 nanard Exp $
|
||||
# MiniUPnP project
|
||||
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
# Author: Thomas Bernard
|
||||
|
@ -83,7 +83,7 @@ STDOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
|
|||
upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \
|
||||
options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \
|
||||
upnpevents.o upnputils.o getconnstatus.o \
|
||||
upnppinhole.o asyncsendto.o
|
||||
upnppinhole.o asyncsendto.o portinuse.o
|
||||
BSDOBJS = bsd/getifstats.o bsd/ifacewatcher.o bsd/getroute.o
|
||||
SUNOSOBJS = solaris/getifstats.o bsd/ifacewatcher.o bsd/getroute.o
|
||||
MACOBJS = mac/getifstats.o bsd/ifacewatcher.o bsd/getroute.o
|
||||
|
@ -120,10 +120,13 @@ TESTUPNPPERMISSIONSOBJS = testupnppermissions.o upnppermissions.o
|
|||
TESTGETIFADDROBJS = testgetifaddr.o getifaddr.o
|
||||
MINIUPNPDCTLOBJS = miniupnpdctl.o
|
||||
TESTASYNCSENDTOOBJS = testasyncsendto.o asyncsendto.o upnputils.o bsd/getroute.o
|
||||
TESTPORTINUSEOBJS = testportinuse.o portinuse.o getifaddr.o
|
||||
|
||||
EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \
|
||||
testupnppermissions miniupnpdctl \
|
||||
testgetifaddr testgetroute testasyncsendto
|
||||
testgetifaddr testgetroute testasyncsendto \
|
||||
testportinuse
|
||||
|
||||
.if $(OSNAME) == "Darwin"
|
||||
LIBS =
|
||||
.else
|
||||
|
@ -147,6 +150,7 @@ clean:
|
|||
testupnpdescgen.o \
|
||||
$(MISCOBJS) config.h testgetifstats.o testupnppermissions.o \
|
||||
miniupnpdctl.o testgetifaddr.o testgetroute.o testasyncsendto.o \
|
||||
testportinuse.o \
|
||||
$(PFOBJS) $(IPFOBJS) $(IPFWOBJS)
|
||||
|
||||
install: miniupnpd genuuid
|
||||
|
@ -177,7 +181,7 @@ genuuid:
|
|||
depend: config.h
|
||||
mkdep $(ALLOBJS:.o=.c) testupnpdescgen.c testgetifstats.c \
|
||||
testupnppermissions.c miniupnpdctl.c testgetifaddr.c \
|
||||
testgetroute.c
|
||||
testgetroute.c testportinuse.c testasyncsendto.c
|
||||
|
||||
miniupnpd: config.h $(ALLOBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(ALLOBJS) $(LIBS)
|
||||
|
@ -206,6 +210,9 @@ testgetroute: config.h $(TESTGETROUTEOBJS)
|
|||
testasyncsendto: config.h $(TESTASYNCSENDTOOBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(TESTASYNCSENDTOOBJS)
|
||||
|
||||
testportinuse: config.h $(TESTPORTINUSEOBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(TESTPORTINUSEOBJS) -lkvm
|
||||
|
||||
# gmake :
|
||||
# $(CC) $(CFLAGS) -o $@ $^
|
||||
# BSDmake :
|
||||
|
|
|
@ -43,7 +43,7 @@ ETCINSTALLDIR = $(PREFIX)/etc/miniupnpd
|
|||
MANINSTALLDIR = $(INSTALLPREFIX)/share/man/man8
|
||||
|
||||
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 \
|
||||
options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \
|
||||
upnpevents.o upnputils.o getconnstatus.o \
|
||||
|
@ -150,7 +150,7 @@ TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o
|
|||
|
||||
EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \
|
||||
testupnppermissions miniupnpdctl testgetifaddr \
|
||||
testgetroute testasyncsendto
|
||||
testgetroute testasyncsendto testportinuse
|
||||
|
||||
.PHONY: all clean install depend genuuid
|
||||
|
||||
|
@ -208,6 +208,9 @@ testgetroute: testgetroute.o linux/getroute.o upnputils.o -lnfnetlink
|
|||
testasyncsendto: testasyncsendto.o asyncsendto.o upnputils.o \
|
||||
linux/getroute.o -lnfnetlink
|
||||
|
||||
testportinuse: testportinuse.o portinuse.o getifaddr.o \
|
||||
netfilter/iptcrdr.o $(LIBS)
|
||||
|
||||
miniupnpdctl: miniupnpdctl.o
|
||||
|
||||
config.h: genconfig.sh VERSION
|
||||
|
@ -217,7 +220,8 @@ depend: config.h
|
|||
makedepend -f$(MAKEFILE_LIST) -Y \
|
||||
$(ALLOBJS:.o=.c) $(TESTUPNPDESCGENOBJS:.o=.c) \
|
||||
testgetifstats.c testupnppermissions.c testgetifaddr.c \
|
||||
testgetroute.c testasyncsendto.c miniupnpdctl.c 2>/dev/null
|
||||
testgetroute.c testasyncsendto.c testportinuse.c \
|
||||
miniupnpdctl.c 2>/dev/null
|
||||
|
||||
# DO NOT DELETE
|
||||
|
||||
|
@ -237,8 +241,11 @@ upnpsoap.o: upnpredirect.h upnppinhole.h getifaddr.h getifstats.h
|
|||
upnpsoap.o: getconnstatus.h upnpurns.h
|
||||
upnpreplyparse.o: upnpreplyparse.h minixml.h
|
||||
minixml.o: minixml.h
|
||||
portinuse.o: macros.h config.h upnpglobalvars.h upnppermissions.h
|
||||
portinuse.o: miniupnpdtypes.h getifaddr.h portinuse.h netfilter/iptcrdr.h
|
||||
portinuse.o: commonrdr.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
|
||||
getifaddr.o: config.h getifaddr.h
|
||||
daemonize.o: daemonize.h config.h
|
||||
|
@ -252,11 +259,11 @@ minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h
|
|||
minissdp.o: upnputils.h getroute.h asyncsendto.h codelength.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: asyncsendto.h
|
||||
pcpserver.o: config.h pcpserver.h natpmp.h macros.h upnpglobalvars.h
|
||||
pcpserver.o: upnppermissions.h miniupnpdtypes.h pcplearndscp.h upnpredirect.h
|
||||
pcpserver.o: commonrdr.h getifaddr.h asyncsendto.h upnputils.h
|
||||
pcpserver.o: pcp_msg_struct.h netfilter/iptcrdr.h commonrdr.h
|
||||
natpmp.o: portinuse.h asyncsendto.h
|
||||
pcpserver.o: config.h pcpserver.h macros.h upnpglobalvars.h upnppermissions.h
|
||||
pcpserver.o: miniupnpdtypes.h pcplearndscp.h upnpredirect.h commonrdr.h
|
||||
pcpserver.o: getifaddr.h asyncsendto.h pcp_msg_struct.h netfilter/iptcrdr.h
|
||||
pcpserver.o: commonrdr.h
|
||||
upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h
|
||||
upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h
|
||||
upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h
|
||||
|
@ -289,4 +296,5 @@ testgetifaddr.o: config.h getifaddr.h
|
|||
testgetroute.o: getroute.h upnputils.h upnpglobalvars.h upnppermissions.h
|
||||
testgetroute.o: config.h miniupnpdtypes.h
|
||||
testasyncsendto.o: miniupnpdtypes.h config.h upnputils.h asyncsendto.h
|
||||
testportinuse.o: macros.h config.h portinuse.h
|
||||
miniupnpdctl.o: macros.h
|
||||
|
|
|
@ -33,7 +33,7 @@ STD_OBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
|
|||
upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \
|
||||
options.o upnppermissions.o minissdp.o natpmp.o \
|
||||
upnpevents.o getconnstatus.o upnputils.o \
|
||||
asyncsendto.o
|
||||
asyncsendto.o portinuse.o pcpserver.o
|
||||
MAC_OBJS = mac/getifstats.o bsd/ifacewatcher.o
|
||||
IPFW_OBJS = ipfw/ipfwrdr.o ipfw/ipfwaux.o
|
||||
PF_OBJS = pf/obsdrdr.o pf/pfpinhole.o
|
||||
|
@ -51,11 +51,13 @@ TEST_UPNPDESCGEN_OBJS = testupnpdescgen.o upnpdescgen.o
|
|||
TEST_GETIFSTATS_OBJS = testgetifstats.o mac/getifstats.o
|
||||
TEST_UPNPPERMISSIONS_OBJS = testupnppermissions.o upnppermissions.o
|
||||
TEST_GETIFADDR_OBJS = testgetifaddr.o getifaddr.o
|
||||
TEST_PORTINUSE_OBJS = testportinuse.o portinuse.o getifaddr.o
|
||||
TEST_ASYNCSENDTO_OBJS = testasyncsendto.o asyncsendto.o upnputils.o
|
||||
MINIUPNPDCTL_OBJS = miniupnpdctl.o
|
||||
|
||||
EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \
|
||||
testupnppermissions miniupnpdctl \
|
||||
testgetifaddr
|
||||
testgetifaddr testportinuse testasyncsendto
|
||||
|
||||
LIBS =
|
||||
|
||||
|
@ -116,6 +118,11 @@ testgetifaddr: config.h $(TEST_GETIFADDR_OBJS)
|
|||
testupnppermissions: config.h $(TEST_UPNPPERMISSIONS_OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(TEST_UPNPPERMISSIONS_OBJS)
|
||||
|
||||
testasyncsendto: config.h $(TEST_ASYNCSENDTO_OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(TEST_ASYNCSENDTO_OBJS)
|
||||
|
||||
testportinuse: config.h $(TEST_PORTINUSE_OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(TEST_PORTINUSE_OBJS)
|
||||
|
||||
config.h: genconfig.sh
|
||||
./genconfig.sh
|
||||
|
|
|
@ -33,3 +33,4 @@ use non blocking sockets everywhere :
|
|||
- NAT-PMP => OK
|
||||
- not needed for miniupnpdctl
|
||||
|
||||
implement port_in_use() for NetBSD and FreeBSD
|
||||
|
|
|
@ -14,6 +14,7 @@ case "$argv" in
|
|||
--leasefile) LEASEFILE=1 ;;
|
||||
--vendorcfg) VENDORCFG=1 ;;
|
||||
--pcp-peer) PCP_PEER=1 ;;
|
||||
--portinuse) PORTINUSE=1 ;;
|
||||
--help|-h)
|
||||
echo "Usage : $0 [options]"
|
||||
echo " --ipv6 enable IPv6"
|
||||
|
@ -22,6 +23,7 @@ case "$argv" in
|
|||
echo " --leasefile enable lease file"
|
||||
echo " --vendorcfg enable configuration of manufacturer info"
|
||||
echo " --pcp-peer enable PCP PEER operation"
|
||||
echo " --portinuse enable port in use check"
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
|
@ -395,6 +397,14 @@ else
|
|||
fi
|
||||
echo "" >> ${CONFIGFILE}
|
||||
|
||||
echo "/* Uncomment the following line to enable port in use check */" >> ${CONFIGFILE}
|
||||
if [ -n "$PORTINUSE" ]; then
|
||||
echo "#define CHECK_PORTINUSE" >> ${CONFIGFILE}
|
||||
else
|
||||
echo "/*#define CHECK_PORTINUSE*/" >> ${CONFIGFILE}
|
||||
fi
|
||||
echo "" >> ${CONFIGFILE}
|
||||
|
||||
echo "/* Define one or none of the two following macros in order to make some" >> ${CONFIGFILE}
|
||||
echo " * clients happy. It will change the XML Root Description of the IGD." >> ${CONFIGFILE}
|
||||
echo " * Enabling the Layer3Forwarding Service seems to be the more compatible" >> ${CONFIGFILE}
|
||||
|
@ -497,7 +507,7 @@ else
|
|||
fi
|
||||
echo "" >> ${CONFIGFILE}
|
||||
|
||||
echo "#endif" >> ${CONFIGFILE}
|
||||
echo "#endif /* ${CONFIGMACRO} */" >> ${CONFIGFILE}
|
||||
|
||||
${MV} ${CONFIGFILE} ${CONFIGFILE_FINAL}
|
||||
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
#include "upnpredirect.h"
|
||||
#include "commonrdr.h"
|
||||
#include "upnputils.h"
|
||||
#include "portinuse.h"
|
||||
#include "asyncsendto.h"
|
||||
|
||||
#ifdef ENABLE_NATPMP
|
||||
|
||||
|
||||
int OpenAndConfNATPMPSocket(in_addr_t addr)
|
||||
{
|
||||
int snatpmp;
|
||||
|
@ -294,6 +296,15 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
|
|||
continue;
|
||||
}
|
||||
any_eport_allowed = 1; /* at lease one eport is allowed */
|
||||
#ifdef CHECK_PORTINUSE
|
||||
if (port_in_use(ext_if_name, eport, proto, senderaddrstr, iport) > 0) {
|
||||
syslog(LOG_INFO, "port %hu protocol %s already in use",
|
||||
eport, (proto==IPPROTO_TCP)?"tcp":"udp");
|
||||
eport++;
|
||||
if(eport == 0) eport++; /* skip port zero */
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
r = get_redirect_rule(ext_if_name, eport, proto,
|
||||
iaddr_old, sizeof(iaddr_old),
|
||||
&iport_old, 0, 0, 0, 0,
|
||||
|
|
|
@ -284,6 +284,22 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
|
|||
char * rhost, int rhostlen,
|
||||
unsigned int * timestamp,
|
||||
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;
|
||||
IPTC_HANDLE h;
|
||||
|
@ -301,18 +317,18 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
|
|||
iptc_strerror(errno));
|
||||
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
|
||||
{
|
||||
#ifdef IPTABLES_143
|
||||
for(e = iptc_first_rule(miniupnpd_nat_chain, h);
|
||||
for(e = iptc_first_rule(nat_chain_name, h);
|
||||
e;
|
||||
e = iptc_next_rule(e, h))
|
||||
#else
|
||||
for(e = iptc_first_rule(miniupnpd_nat_chain, &h);
|
||||
for(e = iptc_first_rule(nat_chain_name, &h);
|
||||
e;
|
||||
e = iptc_next_rule(e, &h))
|
||||
#endif
|
||||
|
|
|
@ -49,6 +49,13 @@ get_peer_rule_by_index(int index,
|
|||
char * rhost, int rhostlen, unsigned short * rport,
|
||||
unsigned int * timestamp,
|
||||
u_int64_t * packets, u_int64_t * 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);
|
||||
|
||||
/* for debug */
|
||||
int
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
/* $Id: $ */
|
||||
/* MiniUPnP project
|
||||
* (c) 2007-2014 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 */
|
||||
#if defined(__DragonFly__)
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#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>
|
||||
#if defined(__OpenBSD__)
|
||||
#include <sys/queue.h>
|
||||
#include <kvm.h>
|
||||
#include <fcntl.h>
|
||||
#include <nlist.h>
|
||||
#include <limits.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#endif
|
||||
|
||||
#if defined(__DragonFly__)
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
/* sys/socketvar.h must be included above the following headers */
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/tcp_var.h>
|
||||
#endif
|
||||
|
||||
#include "macros.h"
|
||||
#include "config.h"
|
||||
#include "upnpglobalvars.h"
|
||||
#include "getifaddr.h"
|
||||
#include "portinuse.h"
|
||||
|
||||
#if defined(USE_NETFILTER)
|
||||
#include "netfilter/iptcrdr.h"
|
||||
#endif
|
||||
|
||||
#ifdef CHECK_PORTINUSE
|
||||
|
||||
#if defined(USE_NETFILTER)
|
||||
/* Hardcoded for now. Ideally would come from .conf file */
|
||||
char *chains_to_check[] = { "PREROUTING" , 0 };
|
||||
#endif
|
||||
|
||||
int
|
||||
port_in_use(const char *if_name,
|
||||
unsigned eport, int proto,
|
||||
const char *iaddr, unsigned iport)
|
||||
{
|
||||
int found = 0;
|
||||
char ip_addr_str[INET_ADDRSTRLEN];
|
||||
struct in_addr ip_addr;
|
||||
#ifdef __linux__
|
||||
/* linux code */
|
||||
char line[256];
|
||||
FILE *f;
|
||||
const char * tcpfile = "/proc/net/tcp";
|
||||
const char * udpfile = "/proc/net/udp";
|
||||
#endif
|
||||
|
||||
if(getifaddr(if_name, ip_addr_str, INET_ADDRSTRLEN, &ip_addr, NULL) < 0)
|
||||
ip_addr.s_addr = 0;
|
||||
|
||||
syslog(LOG_DEBUG, "Check protocol %s for port %d on ext_if %s %s, %08X",
|
||||
(proto==IPPROTO_TCP)?"tcp":"udp", eport, if_name,
|
||||
ip_addr_str, (unsigned)ip_addr.s_addr);
|
||||
|
||||
/* Phase 1 : check for local sockets (would be listed by netstat) */
|
||||
#if defined(__linux__)
|
||||
f = fopen((proto==IPPROTO_TCP)?tcpfile:udpfile, "r");
|
||||
if (!f) {
|
||||
syslog(LOG_ERR, "cannot open %s", (proto==IPPROTO_TCP)?tcpfile:udpfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 */
|
||||
#ifdef DEBUG
|
||||
syslog(LOG_DEBUG, "port_in_use check port %d and address %s", tmp_port, eaddr);
|
||||
#endif
|
||||
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);
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
static struct nlist list[] = {
|
||||
#if 0
|
||||
{"_tcpstat", 0, 0, 0, 0},
|
||||
{"_udpstat", 0, 0, 0, 0},
|
||||
{"_tcbinfo", 0, 0, 0, 0},
|
||||
{"_udbinfo", 0, 0, 0, 0},
|
||||
#endif
|
||||
{"_tcbtable", 0, 0, 0, 0},
|
||||
{"_udbtable", 0, 0, 0, 0},
|
||||
{NULL,0, 0, 0, 0}
|
||||
};
|
||||
char errstr[_POSIX2_LINE_MAX];
|
||||
kvm_t *kd;
|
||||
ssize_t n;
|
||||
struct inpcbtable table;
|
||||
struct inpcb *next;
|
||||
struct inpcb inpcb;
|
||||
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errstr);
|
||||
if(!kd) {
|
||||
syslog(LOG_ERR, "%s: kvm_openfiles(): %s",
|
||||
"portinuse()", errstr);
|
||||
return -1;
|
||||
}
|
||||
if(kvm_nlist(kd, list) < 0) {
|
||||
syslog(LOG_ERR, "%s: kvm_nlist(): %s",
|
||||
"portinuse()", kvm_geterr(kd));
|
||||
kvm_close(kd);
|
||||
return -1;
|
||||
}
|
||||
n = kvm_read(kd, list[(proto==IPPROTO_TCP)?0:1].n_value, &table, sizeof(table));
|
||||
if(n < 0) {
|
||||
syslog(LOG_ERR, "%s: kvm_read(): %s",
|
||||
"portinuse()", kvm_geterr(kd));
|
||||
kvm_close(kd);
|
||||
return -1;
|
||||
}
|
||||
next = CIRCLEQ_FIRST(&table.inpt_queue); /*TAILQ_FIRST(&table.inpt_queue);*/
|
||||
while(next != NULL) {
|
||||
if(((u_long)next & 3) != 0) break;
|
||||
n = kvm_read(kd, (u_long)next, &inpcb, sizeof(inpcb));
|
||||
if(n < 0) {
|
||||
syslog(LOG_ERR, "kvm_read(): %s", kvm_geterr(kd));
|
||||
break;
|
||||
}
|
||||
next = CIRCLEQ_NEXT(&inpcb, inp_queue); /*TAILQ_NEXT(&inpcb, inp_queue);*/
|
||||
/* skip IPv6 sockets */
|
||||
if((inpcb.inp_flags & INP_IPV6) != 0)
|
||||
continue;
|
||||
#ifdef DEBUG
|
||||
syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu",
|
||||
(u_long)inpcb.inp_laddr.s_addr, ntohs(inpcb.inp_lport),
|
||||
(u_long)inpcb.inp_faddr.s_addr, ntohs(inpcb.inp_fport));
|
||||
#endif
|
||||
if(eport == (unsigned)ntohs(inpcb.inp_lport)) {
|
||||
if(inpcb.inp_laddr.s_addr == INADDR_ANY || inpcb.inp_laddr.s_addr == ip_addr.s_addr) {
|
||||
found++;
|
||||
break; /* don't care how many, just that we found at least one */
|
||||
}
|
||||
}
|
||||
}
|
||||
kvm_close(kd);
|
||||
|
||||
#elif defined(__DragonFly__)
|
||||
const char *varname;
|
||||
struct xinpcb *xip;
|
||||
struct xtcpcb *xtp;
|
||||
struct inpcb *inp;
|
||||
void *buf = NULL;
|
||||
void *so_begin, *so_end;
|
||||
|
||||
size_t len;
|
||||
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
varname = "net.inet.tcp.pcblist";
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
varname = "net.inet.udp.pcblist";
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "port_in_use() unknown proto=%d", proto);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sysctlbyname(varname, NULL, &len, NULL, 0) < 0) {
|
||||
syslog(LOG_ERR, "sysctlbyname(%s, NULL, ...): %m", varname);
|
||||
return -1;
|
||||
}
|
||||
buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
syslog(LOG_ERR, "malloc(%u) failed", (unsigned)len);
|
||||
return -1;
|
||||
}
|
||||
if (sysctlbyname(varname, buf, &len, NULL, 0) < 0) {
|
||||
syslog(LOG_ERR, "sysctlbyname(%s, buf, ...): %m", varname);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
so_begin = buf;
|
||||
so_end = (uint8_t *)buf + len;
|
||||
for (so_begin = buf, so_end = (uint8_t *)so_begin + len;
|
||||
(uint8_t *)so_begin + sizeof(size_t) < (uint8_t *)so_end &&
|
||||
(uint8_t *)so_begin + *(size_t *)so_begin <= (uint8_t *)so_end;
|
||||
so_begin = (uint8_t *)so_begin + *(size_t *)so_begin) {
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
xtp = (struct xtcpcb *)so_begin;
|
||||
if (xtp->xt_len != sizeof *xtp) {
|
||||
syslog(LOG_WARNING, "struct xtcpcb size mismatch; %ld vs %ld",
|
||||
(long)xtp->xt_len, sizeof *xtp);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
inp = &xtp->xt_inp;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
xip = (struct xinpcb *)so_begin;
|
||||
if (xip->xi_len != sizeof *xip) {
|
||||
syslog(LOG_WARNING, "struct xinpcb size mismatch : %ld vs %ld",
|
||||
(long)xip->xi_len, sizeof *xip);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
inp = &xip->xi_inp;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
/* no support for IPv6 */
|
||||
if ((inp->inp_vflag & INP_IPV6) != 0)
|
||||
continue;
|
||||
syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu <=> %hu %08lx:%hu",
|
||||
(u_long)inp->inp_laddr.s_addr, ntohs(inp->inp_lport),
|
||||
(u_long)inp->inp_faddr.s_addr, ntohs(inp->inp_fport),
|
||||
eport, (u_long)ip_addr.s_addr, iport
|
||||
);
|
||||
if (eport == (unsigned)ntohs(inp->inp_lport)) {
|
||||
if (inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_laddr.s_addr == ip_addr.s_addr) {
|
||||
found++;
|
||||
break; /* don't care how many, just that we found at least one */
|
||||
}
|
||||
}
|
||||
}
|
||||
if(buf) {
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
/* #elif __NetBSD__ */
|
||||
/* #elif __FreeBSD__ */
|
||||
/* TODO : FreeBSD / NetBSD / Darwin (OS X) / Solaris code */
|
||||
#else
|
||||
#error "No port_in_use() implementation available for this OS"
|
||||
#endif
|
||||
|
||||
/* Phase 2 : check existing mappings
|
||||
* TODO : implement for pf/ipfw/etc. */
|
||||
#if defined(USE_NETFILTER)
|
||||
if (!found) {
|
||||
char iaddr_old[16];
|
||||
unsigned short iport_old;
|
||||
int i;
|
||||
for (i = 0; chains_to_check[i]; 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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else /* USE_NETFILTER */
|
||||
UNUSED(iport); UNUSED(iaddr);
|
||||
#endif /* USE_NETFILTER */
|
||||
return found;
|
||||
}
|
||||
#endif /* CHECK_PORTINUSE */
|
|
@ -0,0 +1,23 @@
|
|||
/* $Id: $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2014 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#ifndef __PORTINUSE_H__
|
||||
#define __PORTINUSE_H__
|
||||
|
||||
#ifdef CHECK_PORTINUSE
|
||||
/* portinuse()
|
||||
* determine wether a port is already in use
|
||||
* on a given interface.
|
||||
* returns: 0 not in use, > 0 in use
|
||||
* -1 in case of error */
|
||||
int
|
||||
port_in_use(const char *if_name,
|
||||
unsigned port, int proto,
|
||||
const char *iaddr, unsigned iport);
|
||||
#endif /* CHECK_PORTINUSE */
|
||||
|
||||
#endif
|
|
@ -72,7 +72,7 @@ int test(void)
|
|||
struct timeval timeout;
|
||||
struct timeval now;
|
||||
syslog(LOG_DEBUG, "get_next_scheduled_send : %d next_send=%ld.%06ld",
|
||||
i, next_send.tv_sec, next_send.tv_usec);
|
||||
i, (long)next_send.tv_sec, (long)next_send.tv_usec);
|
||||
FD_ZERO(&writefds);
|
||||
max_fd = 0;
|
||||
gettimeofday(&now, NULL);
|
||||
|
@ -98,7 +98,7 @@ int test(void)
|
|||
}
|
||||
syslog(LOG_DEBUG, "get_sendto_fds() returned %d", i);
|
||||
syslog(LOG_DEBUG, "select(%d, NULL, xx, NULL, %ld.%06ld)",
|
||||
max_fd, timeout.tv_sec, timeout.tv_usec);
|
||||
max_fd, (long)timeout.tv_sec, (long)timeout.tv_usec);
|
||||
i = select(max_fd, NULL, &writefds, NULL, &timeout);
|
||||
if(i < 0) {
|
||||
syslog(LOG_ERR, "select: %m");
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* $Id: testportinuse.c,v 1.1.2.5 2014/03/14 11:12:08 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* (c) 2014 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "macros.h"
|
||||
#include "config.h"
|
||||
#include "portinuse.h"
|
||||
|
||||
#ifdef CHECK_PORTINUSE
|
||||
#ifdef USE_NETFILTER
|
||||
const char * miniupnpd_nat_chain = "MINIUPNPD";
|
||||
const char * miniupnpd_peer_chain = "MINIUPNPD-PCP-PEER";
|
||||
const char * miniupnpd_forward_chain = "MINIUPNPD";
|
||||
#endif /* USE_NETFILTER */
|
||||
#endif /* CHECK_PORTINUSE */
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
#ifndef CHECK_PORTINUSE
|
||||
UNUSED(argc); UNUSED(argv);
|
||||
printf("CHECK_PORTINUSE is not defined.\n");
|
||||
#else /* CHECK_PORTINUSE */
|
||||
int r;
|
||||
const char * if_name;
|
||||
unsigned eport;
|
||||
int proto;
|
||||
const char * iaddr;
|
||||
unsigned iport;
|
||||
|
||||
if(argc <= 5) {
|
||||
fprintf(stderr, "usage: %s if_name eport (tcp|udp) iaddr iport\n",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
openlog("testportinuse", LOG_CONS|LOG_PERROR, LOG_USER);
|
||||
if_name = argv[1];
|
||||
eport = (unsigned)atoi(argv[2]);
|
||||
proto = (0==strcmp(argv[3], "tcp"))?IPPROTO_TCP:IPPROTO_UDP;
|
||||
iaddr = argv[4];
|
||||
iport = (unsigned)atoi(argv[5]);
|
||||
|
||||
r = port_in_use(if_name, eport, proto, iaddr, iport);
|
||||
printf("port_in_use(%s, %u, %d, %s, %u) returned %d\n",
|
||||
if_name, eport, proto, iaddr, iport, r);
|
||||
closelog();
|
||||
#endif /* CHECK_PORTINUSE */
|
||||
return 0;
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
#include "upnpredirect.h"
|
||||
#include "upnpglobalvars.h"
|
||||
#include "upnpevents.h"
|
||||
#include "portinuse.h"
|
||||
#if defined(USE_NETFILTER)
|
||||
#include "netfilter/iptcrdr.h"
|
||||
#endif
|
||||
|
@ -294,6 +295,12 @@ upnp_redirect(const char * rhost, unsigned short eport,
|
|||
eport, protocol, iaddr_old, iport_old);
|
||||
return -2;
|
||||
}
|
||||
#ifdef CHECK_PORTINUSE
|
||||
} else if (port_in_use(ext_if_name, eport, proto, iaddr, iport) > 0) {
|
||||
syslog(LOG_INFO, "port %hu protocol %s already in use",
|
||||
eport, protocol);
|
||||
return -2;
|
||||
#endif /* CHECK_PORTINUSE */
|
||||
} else {
|
||||
timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0;
|
||||
syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
|
||||
|
|
Loading…
Reference in New Issue