Merge branch 'master' into portinuse

This commit is contained in:
Thomas Bernard 2013-12-13 12:29:01 +01:00
commit 9b72af6f36
75 changed files with 4567 additions and 376 deletions

2
README
View File

@ -43,4 +43,4 @@ Thanks to :
* David Kerr
* Jardel Weyrich
* Leah X. Schmidt
* Leo Moll

View File

@ -1,4 +1,11 @@
$Id: Changelog.txt,v 1.30 2012/05/24 18:04:56 nanard Exp $
$Id: Changelog.txt,v 1.32 2013/08/19 16:40:55 nanard Exp $
2013/08/19:
Translate README in english
2012/09/27:
Rename all include guards to not clash with C99
(7.1.3 Reserved identifiers).
VERSION 1.2:

View File

@ -1,36 +1,37 @@
protocole :
protocol :
connection à la socket unix.
envoie d'une requete, retour d'une reponse.
fermeture de la connexion.
Connect to the unix socket.
Sent request, answer response.
close unix socket connection.
format de requete :
1 octet : type de la requete
Request format :
1st byte : request type
1 - type
2 - USN (id unique)
3 - tout
n octets longueur de la chaine : 1 octet si < 128 sinon le bit haut
indique s'il existe un octet suplementaire, etc...
n octets = chaine
2 - USN (unique id)
3 - everything
4 - submit service (see below)
n bytes : string length : 1 byte if < 128 else the upper bit indicate that
one additional byte should be read, etc. (see codelength.h)
n bytes = string
format reponse :
1 octet : nombre de reponses
pour chaque rep :
Response format :
1st byte : number of services/devices
For each service/device :
URL :
n octets longueur de la chaine
n octets = chaine Location
n bytes string length
n bytes = Location string
ST:
n octets longueur de la chaine
n octets = chaine type
n bytes string length
n bytes = type string
USN:
n octets longueur de la chaine
n octets = chaine identifiant
n bytes string length
n bytes = identifier string
Type de requete 4 = submit service
1 octet = 4
(k,n) octets : longueur et chaine "ST" (service type)
(k,n) octets : longueur et chaine "USN"
(k,n) octets : longueur et chaine "Server"
(k,n) octets : longueur et chaine "Location"
Pas de reponse
request type 4 = submit service
1st byte = 4
(k,n) bytes : length and string "ST" (service type)
(k,n) bytes : length and string "USN"
(k,n) bytes : length and string "Server"
(k,n) bytes : length and string "Location"
No answer

36
minissdpd/README.fr Normal file
View File

@ -0,0 +1,36 @@
protocole :
connection à la socket unix.
envoie d'une requete, retour d'une reponse.
fermeture de la connexion.
format de requete :
1 octet : type de la requete
1 - type
2 - USN (id unique)
3 - tout
n octets longueur de la chaine : 1 octet si < 128 sinon le bit haut
indique s'il existe un octet suplementaire, etc...
n octets = chaine
format reponse :
1 octet : nombre de reponses
pour chaque rep :
URL :
n octets longueur de la chaine
n octets = chaine Location
ST:
n octets longueur de la chaine
n octets = chaine type
USN:
n octets longueur de la chaine
n octets = chaine identifiant
Type de requete 4 = submit service
1 octet = 4
(k,n) octets : longueur et chaine "ST" (service type)
(k,n) octets : longueur et chaine "USN"
(k,n) octets : longueur et chaine "Server"
(k,n) octets : longueur et chaine "Location"
Pas de reponse

View File

@ -1,13 +1,15 @@
/* $Id: upnputils.c,v 1.5 2012/05/24 16:51:09 nanard Exp $ */
/* $Id: upnputils.c,v 1.1 2013/09/07 06:45:39 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>

View File

@ -1,7 +1,7 @@
/* $Id: upnputils.h,v 1.2 2012/02/06 16:21:24 nanard Exp $ */
/* $Id: upnputils.h,v 1.1 2013/09/07 06:45:39 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011-2012 Thomas Bernard
* (c) 2011-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */

View File

@ -19,3 +19,6 @@ java/miniupnpc_*.jar
_jnaerator.*
out.errors.txt
jnaerator-*.jar
miniupnpc.h.bak
testupnpreplyparse
validateupnpreplyparse

View File

@ -1,6 +1,41 @@
$Id: Changelog.txt,v 1.180 2012/10/16 16:49:39 nanard Exp $
$Id: Changelog.txt,v 1.189 2013/10/07 10:04:55 nanard Exp $
miniUPnP client Changelog.
2013/12/09:
--help and -h arguments in upnpc.c
2013/10/07:
fixed potential buffer overrun in miniwget.c
Modified UPNP_GetValidIGD() to check for ExternalIpAddress
2013/08/01:
define MAXHOSTNAMELEN if not already done
2013/06/06:
update upnpreplyparse to allow larger values (128 chars instead of 64)
2013/05/14:
Update upnpreplyparse to take into account "empty" elements
validate upnpreplyparse.c code with "make check"
2013/05/03:
Fix Solaris build thanks to Maciej Małecki
2013/04/27:
Fix testminiwget.sh for BSD
2013/03/23:
Fixed Makefile for *BSD
2013/03/11:
Update Makefile to use JNAerator version 0.11
2013/02/11:
Fix testminiwget.sh for use with dash
Use $(DESTDIR) in Makefile
VERSION 1.8 : released 2013/02/06
2012/10/16:
fix testminiwget with no IPv6 support

View File

@ -1,15 +1,15 @@
# $Id: Makefile,v 1.96 2012/06/23 22:30:42 nanard Exp $
# $Id: Makefile,v 1.105 2013/05/14 20:37:36 nanard Exp $
# MiniUPnP Project
# http://miniupnp.free.fr/
# http://miniupnp.tuxfamily.org/
# https://github.com/miniupnp/miniupnp
# (c) 2005-2012 Thomas Bernard
# (c) 2005-2013 Thomas Bernard
# to install use :
# $ PREFIX=/tmp/dummylocation make install
# $ make DESTDIR=/tmp/dummylocation install
# or
# $ INSTALLPREFIX=/usr/local make install
# or
# make install (will go to /usr/bin, /usr/lib, etc...)
# $ make install (default INSTALLPREFIX is /usr)
OS = $(shell uname -s)
VERSION = $(shell cat VERSION)
@ -42,10 +42,17 @@ INSTALL = install
SH = /bin/sh
JAVA = java
# see http://code.google.com/p/jnaerator/
JNAERATOR = jnaerator-0.9.7.jar
#JNAERATOR = jnaerator-0.9.7.jar
#JNAERATOR = jnaerator-0.9.8-shaded.jar
#JNAERATORARGS = -library miniupnpc
#JNAERATOR = jnaerator-0.10-shaded.jar
JNAERATOR = jnaerator-0.11-shaded.jar
JNAERATORARGS = -mode StandaloneJar -runtime JNAerator -library miniupnpc
JNAERATORBASEURL = http://jnaerator.googlecode.com/files/
#following libs are needed on Solaris
#LDLIBS=-lsocket -lnsl -lresolv
ifeq (SunOS, $(OS))
LDFLAGS=-lsocket -lnsl -lresolv
endif
# APIVERSION is used to build SONAME
APIVERSION = 9
@ -80,12 +87,12 @@ ifeq ($(OS), Darwin)
SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib
CFLAGS := -DMACOSX -D_DARWIN_C_SOURCE $(CFLAGS)
else
ifeq ($(OS), Linux)
SHAREDLIBRARY = libminiupnpc.so
SONAME = $(SHAREDLIBRARY).$(APIVERSION)
endif
ifeq ($(JARSUFFIX), win32)
SHAREDLIBRARY = miniupnpc.dll
else
# Linux/BSD/etc.
SHAREDLIBRARY = libminiupnpc.so
SONAME = $(SHAREDLIBRARY).$(APIVERSION)
endif
endif
@ -132,7 +139,7 @@ all: $(LIBRARY) $(EXECUTABLES)
test: check
check: validateminixml validateminiwget
check: validateminixml validateminiwget validateupnpreplyparse
everything: all $(EXECUTABLES_ADDTESTS)
@ -160,6 +167,11 @@ validateminiwget: testminiwget minihttptestserver testminiwget.sh
./testminiwget.sh
touch $@
validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh
@echo "upnpreplyparse validation test"
./testupnpreplyparse.sh
touch $@
clean:
$(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h
# clean python stuff
@ -177,31 +189,34 @@ updateversion: miniupnpc.h
sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < miniupnpc.h.bak > miniupnpc.h
install: updateversion $(FILESTOINSTALL)
$(INSTALL) -d $(INSTALLDIRINC)
$(INSTALL) -m 644 $(HEADERS) $(INSTALLDIRINC)
$(INSTALL) -d $(INSTALLDIRLIB)
$(INSTALL) -m 644 $(LIBRARY) $(INSTALLDIRLIB)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB)
$(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB)
ifneq ($(OS), AmigaOS)
$(INSTALL) -m 644 $(SHAREDLIBRARY) $(INSTALLDIRLIB)/$(SONAME)
ln -fs $(SONAME) $(INSTALLDIRLIB)/$(SHAREDLIBRARY)
$(INSTALL) -m 644 $(SHAREDLIBRARY) $(DESTDIR)$(INSTALLDIRLIB)/$(SONAME)
ln -fs $(SONAME) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
endif
$(INSTALL) -d $(INSTALLDIRBIN)
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN)
ifeq ($(OS), AmigaOS)
$(INSTALL) -m 755 upnpc-static $(INSTALLDIRBIN)/upnpc
$(INSTALL) -m 755 upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc
else
$(INSTALL) -m 755 upnpc-shared $(INSTALLDIRBIN)/upnpc
$(INSTALL) -m 755 upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc
endif
$(INSTALL) -m 755 external-ip.sh $(INSTALLDIRBIN)/external-ip
$(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip
ifneq ($(OS), AmigaOS)
$(INSTALL) -d $(INSTALLDIRMAN)/man3
$(INSTALL) man3/miniupnpc.3 $(INSTALLDIRMAN)/man3/miniupnpc.3
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRMAN)/man3
$(INSTALL) man3/miniupnpc.3 $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
ifeq ($(OS), Linux)
gzip $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
endif
endif
cleaninstall:
$(RM) -r $(INSTALLDIRINC)
$(RM) $(INSTALLDIRLIB)/$(LIBRARY)
$(RM) $(INSTALLDIRLIB)/$(SHAREDLIBRARY)
$(RM) -r $(DESTDIR)$(INSTALLDIRINC)
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY)
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
depend:
makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null
@ -217,10 +232,10 @@ else
$(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^
endif
upnpc-static: upnpc.o $(LIBRARY) $(LDLIBS)
upnpc-static: upnpc.o $(LIBRARY)
$(CC) $(LDFLAGS) -o $@ $^
upnpc-shared: upnpc.o $(SHAREDLIBRARY) $(LDLIBS)
upnpc-shared: upnpc.o $(SHAREDLIBRARY)
$(CC) $(LDFLAGS) -o $@ $^
testminixml: $(TESTMINIXMLOBJS)
@ -236,17 +251,14 @@ testigddescparse: $(TESTIGDDESCPARSE)
miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION
$(SH) updateminiupnpcstrings.sh
jnaerator-0.9.8-shaded.jar:
wget $(JNAERATORBASEURL)/$@ || curl -o $@ $(JNAERATORBASEURL)/$@
jnaerator-0.9.7.jar:
wget $(JNAERATORBASEURL)/$@ || curl -o $@ $(JNAERATORBASEURL)/$@
jnaerator-0.9.3.jar:
wget $(JNAERATORBASEURL)/$@ || curl -o $@ $(JNAERATORBASEURL)/$@
# ftp tool supplied with OpenBSD can download files from http.
jnaerator-%.jar:
wget $(JNAERATORBASEURL)/$@ || \
curl -o $@ $(JNAERATORBASEURL)/$@ || \
ftp $(JNAERATORBASEURL)/$@
jar: $(SHAREDLIBRARY) $(JNAERATOR)
$(JAVA) -jar $(JNAERATOR) -library miniupnpc \
$(JAVA) -jar $(JNAERATOR) $(JNAERATORARGS) \
miniupnpc.h declspec.h upnpcommands.h upnpreplyparse.h \
igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) \
-package fr.free.miniupnp -o . -jar java/miniupnpc_$(JARSUFFIX).jar -v

117
miniupnpc/apiversions.txt Normal file
View File

@ -0,0 +1,117 @@
$Id: apiversions.txt,v 1.2 2013/03/29 14:45:09 nanard Exp $
Differences in API between miniUPnPc versions
====================== miniUPnPc version 1.8 ======================
API version 9
miniupnpc.h:
updated macros :
#define MINIUPNPC_VERSION "1.8"
#define MINIUPNPC_API_VERSION 9
added "unsigned int scope_id;" to struct UPNPDev
added scope_id argument to GetUPNPUrls()
====================== miniUPnPc version 1.7 ======================
API version 8
miniupnpc.h :
add new macros :
#define MINIUPNPC_VERSION "1.7"
#define MINIUPNPC_API_VERSION 8
add rootdescURL to struct UPNPUrls
====================== miniUPnPc version 1.6 ======================
API version 8
Adding support for IPv6.
igd_desc_parse.h :
struct IGDdatas_service :
add char presentationurl[MINIUPNPC_URL_MAXSIZE];
struct IGDdatas :
add struct IGDdatas_service IPv6FC;
miniupnpc.h :
new macros :
#define UPNPDISCOVER_SUCCESS (0)
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
#define UPNPDISCOVER_SOCKET_ERROR (-101)
#define UPNPDISCOVER_MEMORY_ERROR (-102)
simpleUPnPcommand() prototype changed (but is normaly not used by API users)
add arguments ipv6 and error to upnpDiscover() :
struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport,
int ipv6,
int * error);
add controlURL_6FC member to struct UPNPUrls :
struct UPNPUrls {
char * controlURL;
char * ipcondescURL;
char * controlURL_CIF;
char * controlURL_6FC;
};
upnpcommands.h :
add leaseDuration argument to UPNP_AddPortMapping()
add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry()
add UPNP_GetListOfPortMappings() function (IGDv2)
add IGDv2 IPv6 related functions :
UPNP_GetFirewallStatus()
UPNP_GetOutboundPinholeTimeout()
UPNP_AddPinhole()
UPNP_UpdatePinhole()
UPNP_DeletePinhole()
UPNP_CheckPinholeWorking()
UPNP_GetPinholePackets()
====================== miniUPnPc version 1.5 ======================
API version 5
new function :
int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
new macro in upnpcommands.h :
#define UPNPCOMMAND_HTTP_ERROR
====================== miniUPnPc version 1.4 ======================
Same API as version 1.3
====================== miniUPnPc version 1.3 ======================
API version 4
Use UNSIGNED_INTEGER type for
UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(),
UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived()
Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping()
====================== miniUPnPc version 1.2 ======================
API version 3
added sameport argument to upnpDiscover()
struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport);
====================== miniUPnPc Version 1.1 ======================
Same API as 1.0
====================== miniUPnPc Version 1.0 ======================
API version 2
struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
char buffer[2];
};
struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock);

View File

@ -1,7 +1,7 @@
/* $Id: connecthostport.c,v 1.9 2012/06/26 00:00:27 nanard Exp $ */
/* $Id: connecthostport.c,v 1.11 2013/08/01 21:21:25 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2010-2012 Thomas Bernard
* Copyright (c) 2010-2013 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@ -24,6 +24,7 @@
#else /* #ifdef _WIN32 */
#include <unistd.h>
#include <sys/param.h>
#include <sys/select.h>
#include <errno.h>
#define closesocket close
#include <netdb.h>
@ -50,6 +51,10 @@
#include "connecthostport.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */

View File

@ -1,5 +1,4 @@
\" $Id: miniupnpc.3,v 1.3 2011/07/25 18:02:11 nanard Exp $
.TH miniupnpc 3
.TH MINIUPNPC 3
.SH NAME
miniupnpc \- UPnP client library
.SH SYNOPSIS

View File

@ -1,8 +1,8 @@
/* $Id: miniupnpc.c,v 1.111 2012/10/09 17:53:14 nanard Exp $ */
/* $Id: miniupnpc.c,v 1.113 2013/10/07 10:04:56 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
* copyright (c) 2005-2012 Thomas Bernard
* copyright (c) 2005-2013 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#define __EXTENSIONS__ 1
@ -71,6 +71,17 @@
#define TIMEVAL struct timeval
#endif
#if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN)
/* Several versions of glibc don't define this structure, define it here and compile with CFLAGS NEED_STRUCT_IP_MREQN */
struct ip_mreqn
{
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_address; /* local IP address of interface */
int imr_ifindex; /* Interface index */
};
#endif
#include "miniupnpc.h"
#include "minissdpc.h"
#include "miniwget.h"
@ -86,6 +97,10 @@
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#define SOAPPREFIX "s"
#define SERVICEPREFIX "u"
#define SERVICEPREFIX2 'u'
@ -867,7 +882,7 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
* not connected
* 3 = an UPnP device has been found but was not recognized as an IGD
*
* In any non zero return case, the urls and data structures
* In any positive non zero return case, the urls and data structures
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
* free allocated memory.
*/
@ -880,11 +895,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
struct xml_desc {
char * xml;
int size;
int is_igd;
} * desc = NULL;
struct UPNPDev * dev;
int ndev = 0;
int i;
int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
int n_igd = 0;
char extIpAddr[16];
if(!devlist)
{
#ifdef DEBUG
@ -892,6 +910,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
#endif
return 0;
}
/* counting total number of devices in the list */
for(dev = devlist; dev; dev = dev->pNext)
ndev++;
if(ndev > 0)
@ -900,41 +919,58 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
if(!desc)
return -1; /* memory allocation error */
}
/* Step 1 : downloading descriptions and testing type */
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
{
/* we should choose an internet gateway device.
* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size),
lanaddr, lanaddrlen,
dev->scope_id);
#ifdef DEBUG
if(!desc[i].xml)
{
printf("error getting XML description %s\n", dev->descURL);
}
#endif
if(desc[i].xml)
{
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(desc[i].xml, desc[i].size, data);
if(0==strcmp(data->CIF.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
{
desc[i].is_igd = 1;
n_igd++;
}
}
}
/* iterate the list to find a device depending on state */
for(state = 1; state <= 3; state++)
{
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
{
/* we should choose an internet gateway device.
* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
if(state == 1)
{
desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size),
lanaddr, lanaddrlen,
dev->scope_id);
#ifdef DEBUG
if(!desc[i].xml)
{
printf("error getting XML description %s\n", dev->descURL);
}
#endif
}
if(desc[i].xml)
{
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(desc[i].xml, desc[i].size, data);
if(0==strcmp(data->CIF.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
|| state >= 3 )
if(desc[i].is_igd || state >= 3 )
{
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
/* in state 2 and 3 we dont test if device is connected ! */
if(state >= 2)
goto free_and_return;
#ifdef DEBUG
printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL,
UPNPIGD_IsConnected(urls, data));
#endif
if((state >= 2) || UPNPIGD_IsConnected(urls, data))
/* checks that status is connected AND there is a external IP address assigned */
if(UPNPIGD_IsConnected(urls, data)
&& (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0))
goto free_and_return;
FreeUPNPUrls(urls);
if(data->second.servicetype[0] != '\0') {
@ -952,7 +988,8 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
urls->controlURL,
UPNPIGD_IsConnected(urls, data));
#endif
if((state >= 2) || UPNPIGD_IsConnected(urls, data))
if(UPNPIGD_IsConnected(urls, data)
&& (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0))
goto free_and_return;
FreeUPNPUrls(urls);
}

View File

@ -1,8 +1,8 @@
/* $Id: miniwget.c,v 1.58 2012/08/11 05:52:49 nanard Exp $ */
/* $Id: miniwget.c,v 1.60 2013/10/07 10:03:16 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* Copyright (c) 2005-2013 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@ -52,6 +52,10 @@
#include "connecthostport.h"
#include "receivedata.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/*
* Read a HTTP response from a socket.
* Process Content-Length and Transfer-encoding headers.
@ -158,7 +162,7 @@ getHTTPResponse(int s, int * size)
chunked = 1;
}
}
while(header_buf[i]=='\r' || header_buf[i] == '\n')
while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
i++;
linestart = i;
colon = linestart;

View File

@ -1,5 +1,5 @@
#!/bin/sh
# $Id: testminiwget.sh,v 1.6 2012/05/29 13:03:40 nanard Exp $
# $Id: testminiwget.sh,v 1.10 2013/11/13 15:08:08 nanard Exp $
# project miniupnp : http://miniupnp.free.fr/
# (c) 2011-2012 Thomas Bernard
#
@ -13,12 +13,12 @@
# 4 - kills the local HTTP server and exits
#
# The script was tested and works with ksh, bash
# It fails to run with dash 0.5.5.1 because of "kill %1"
# it should now also run with dash
TMPDIR=`mktemp -d`
HTTPSERVEROUT="${TMPDIR}/httpserverout"
EXPECTEDFILE="${TMPDIR}/expectedfile"
DOWNLOADEDFILE="${TMPDIR}/downloadedfile"
TMPD=`mktemp -d miniwgetXXXXXXXXXX`
HTTPSERVEROUT="${TMPD}/httpserverout"
EXPECTEDFILE="${TMPD}/expectedfile"
DOWNLOADEDFILE="${TMPD}/downloadedfile"
PORT=
RET=0
@ -39,6 +39,7 @@ esac
# launching the test HTTP server
./minihttptestserver $SERVERARGS -e $EXPECTEDFILE > $HTTPSERVEROUT &
SERVERPID=$!
while [ -z "$PORT" ]; do
sleep 1
PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' `
@ -77,8 +78,8 @@ else
fi
# kill the test HTTP server
kill %1
wait %1
kill $SERVERPID
wait $SERVERPID
# remove temporary files (for success cases)
if [ $RET -eq 0 ]; then
@ -86,10 +87,10 @@ if [ $RET -eq 0 ]; then
rm -f "${DOWNLOADEDFILE}.2"
rm -f "${DOWNLOADEDFILE}.3"
rm -f $EXPECTEDFILE $HTTPSERVEROUT
rmdir ${TMPDIR}
rmdir ${TMPD}
else
echo "at least one of the test FAILED"
echo "directory ${TMPDIR} is left intact"
echo "directory ${TMPD} is left intact"
fi
exit $RET

View File

@ -1,8 +1,8 @@
/* $Id: testminixml.c,v 1.7 2012/01/21 13:30:33 nanard Exp $
/* $Id: testminixml.c,v 1.9 2013/05/14 19:50:49 nanard Exp $
* MiniUPnP project
* Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard.
* Copyright (c) 2005-2012 Thomas Bernard
* Copyright (c) 2005-2013 Thomas Bernard
*
* testminixml.c
* test program for the "minixml" functions.
@ -17,6 +17,7 @@
void printeltname1(void * d, const char * name, int l)
{
int i;
(void)d;
printf("element ");
for(i=0;i<l;i++)
putchar(name[i]);
@ -24,6 +25,7 @@ void printeltname1(void * d, const char * name, int l)
void printeltname2(void * d, const char * name, int l)
{
int i;
(void)d;
putchar('/');
for(i=0;i<l;i++)
putchar(name[i]);
@ -32,6 +34,7 @@ void printeltname2(void * d, const char * name, int l)
void printdata(void *d, const char * data, int l)
{
int i;
(void)d;
printf("data : ");
for(i=0;i<l;i++)
putchar(data[i]);

View File

@ -0,0 +1,3 @@
NewRemoteHost=
NewExternalPort=123
NewProtocol=TCP

View File

@ -0,0 +1,6 @@
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:DeletePortMapping xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost></NewRemoteHost><NewExternalPort>123</NewExternalPort>
<NewProtocol>TCP</NewProtocol></u:DeletePortMapping></s:Body>
</s:Envelope>

View File

@ -0,0 +1,2 @@
NewExternalIPAddress=1.2.3.4

View File

@ -0,0 +1,2 @@
<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetExternalIPAddressResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewExternalIPAddress>1.2.3.4</NewExternalIPAddress></u:GetExternalIPAddressResponse></s:Body></s:Envelope>

View File

@ -0,0 +1 @@
NewDefaultConnectionService=uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><u:SetDefaultConnectionService xmlns:u="urn:schemas-upnp-org:service:Layer3Forwarding:1"><NewDefaultConnectionService>uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID</NewDefaultConnectionService></u:SetDefaultConnectionService></s:Body></s:Envelope>

View File

@ -0,0 +1,7 @@
This directory contains files used for validation of upnpreplyparse.c code.
Each .xml file to parse should give the results which are in the .namevalue
file.
A .namevalue file contain name=value lines.

View File

@ -1,19 +1,55 @@
/* $Id: testupnpreplyparse.c,v 1.2 2008/02/21 13:05:27 nanard Exp $ */
/* $Id: testupnpreplyparse.c,v 1.3 2013/05/14 20:37:36 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2007 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "upnpreplyparse.h"
void
test_parsing(const char * buf, int len)
int
test_parsing(const char * buf, int len, FILE * f)
{
char line[1024];
struct NameValueParserData pdata;
int ok = 1;
ParseNameValue(buf, len, &pdata);
/* check result */
if(f != NULL)
{
while(fgets(line, sizeof(line), f))
{
char * value;
char * equal;
char * parsedvalue;
int l;
l = strlen(line);
while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n')))
line[--l] = '\0';
/* skip empty lines */
if(l == 0)
continue;
equal = strchr(line, '=');
if(equal == NULL)
{
fprintf(stderr, "Warning, line does not contain '=' : %s\n", line);
continue;
}
*equal = '\0';
value = equal + 1;
parsedvalue = GetValueFromNameValueList(&pdata, line);
if((parsedvalue == NULL) || (strcmp(parsedvalue, value) != 0))
{
fprintf(stderr, "Element <%s> : expecting value '%s', got '%s'\n",
line, value, parsedvalue ? parsedvalue : "<null string>");
ok = 0;
}
}
}
ClearNameValueList(&pdata);
return ok;
}
int main(int argc, char * * argv)
@ -21,9 +57,11 @@ int main(int argc, char * * argv)
FILE * f;
char buffer[4096];
int l;
int ok;
if(argc<2)
{
fprintf(stderr, "Usage: %s file.xml\n", argv[0]);
fprintf(stderr, "Usage: %s file.xml [file.namevalues]\n", argv[0]);
return 1;
}
f = fopen(argv[1], "r");
@ -34,11 +72,25 @@ int main(int argc, char * * argv)
}
l = fread(buffer, 1, sizeof(buffer)-1, f);
fclose(f);
f = NULL;
buffer[l] = '\0';
if(argc >= 2)
{
f = fopen(argv[2], "r");
if(!f)
{
fprintf(stderr, "Error : can not open file %s\n", argv[2]);
return 2;
}
}
#ifdef DEBUG
DisplayNameValueList(buffer, l);
#endif
test_parsing(buffer, l);
return 0;
ok = test_parsing(buffer, l, f);
if(f)
{
fclose(f);
}
return ok ? 0 : 3;
}

14
miniupnpc/testupnpreplyparse.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
for f in testreplyparse/*.xml ; do
bf="`dirname $f`/`basename $f .xml`"
if ./testupnpreplyparse $f $bf.namevalue ; then
echo "$f : passed"
else
echo "$f : FAILED"
exit 1
fi
done
exit 0

View File

@ -506,6 +506,11 @@ int main(int argc, char ** argv)
/* command line processing */
for(i=1; i<argc; i++)
{
if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
{
command = 0;
break;
}
if(argv[i][0] == '-')
{
if(argv[i][1] == 'u')

View File

@ -1,4 +1,4 @@
/* $Id: upnpcommands.c,v 1.40 2012/06/23 22:36:35 nanard Exp $ */
/* $Id: upnpcommands.c,v 1.41 2013/12/09 08:18:23 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
@ -759,7 +759,7 @@ UPNP_GetFirewallStatus(const char * controlURL,
char * fe, *ipa, *p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!firewallEnabled && !inboundPinholeAllowed)
if(!firewallEnabled || !inboundPinholeAllowed)
return UPNPCOMMAND_INVALID_ARGS;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,

View File

@ -1,7 +1,7 @@
/* $Id: upnpreplyparse.c,v 1.11 2011/02/07 16:17:06 nanard Exp $ */
/* $Id: upnpreplyparse.c,v 1.15 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -15,18 +15,55 @@
static void
NameValueParserStartElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValueParserData * data = (struct NameValueParserData *)d;
data->topelt = 1;
if(l>63)
l = 63;
memcpy(data->curelt, name, l);
data->curelt[l] = '\0';
data->cdata = NULL;
data->cdatalen = 0;
}
static void
NameValueParserEndElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
(void)name;
(void)l;
if(!data->topelt)
return;
if(strcmp(data->curelt, "NewPortListing") != 0)
{
int l;
/* standard case. Limited to n chars strings */
l = data->cdatalen;
nv = malloc(sizeof(struct NameValue));
if(l>=(int)sizeof(nv->value))
l = sizeof(nv->value) - 1;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
if(data->cdata != NULL)
{
memcpy(nv->value, data->cdata, l);
nv->value[l] = '\0';
}
else
{
nv->value[0] = '\0';
}
LIST_INSERT_HEAD( &(data->head), nv, entries);
}
data->cdata = NULL;
data->cdatalen = 0;
data->topelt = 0;
}
static void
NameValueParserGetData(void * d, const char * datas, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
if(strcmp(data->curelt, "NewPortListing") == 0)
{
/* specific case for NewPortListing which is a XML Document */
@ -42,15 +79,9 @@ NameValueParserGetData(void * d, const char * datas, int l)
}
else
{
/* standard case. Limited to 63 chars strings */
nv = malloc(sizeof(struct NameValue));
if(l>63)
l = 63;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
memcpy(nv->value, datas, l);
nv->value[l] = '\0';
LIST_INSERT_HEAD( &(data->head), nv, entries);
/* standard case. */
data->cdata = datas;
data->cdatalen = l;
}
}
@ -67,7 +98,7 @@ ParseNameValue(const char * buffer, int bufsize,
parser.xmlsize = bufsize;
parser.data = data;
parser.starteltfunc = NameValueParserStartElt;
parser.endeltfunc = 0;
parser.endeltfunc = NameValueParserEndElt;
parser.datafunc = NameValueParserGetData;
parser.attfunc = 0;
parsexml(&parser);

View File

@ -1,7 +1,7 @@
/* $Id: upnpreplyparse.h,v 1.12 2012/01/21 13:30:33 nanard Exp $ */
/* $Id: upnpreplyparse.h,v 1.17 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -21,7 +21,7 @@ extern "C" {
struct NameValue {
LIST_ENTRY(NameValue) entries;
char name[64];
char value[64];
char value[128];
};
struct NameValueParserData {
@ -29,6 +29,9 @@ struct NameValueParserData {
char curelt[64];
char * portListing;
int portListingLength;
int topelt;
const char * cdata;
int cdatalen;
};
/* ParseNameValue() */
@ -45,10 +48,12 @@ char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name);
#if 0
/* GetValueFromNameValueListIgnoreNS() */
char *
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
const char * Name);
#endif
/* DisplayNameValueList() */
#ifdef DEBUG

View File

@ -1,4 +1,55 @@
$Id: Changelog.txt,v 1.330 2013/02/07 12:22:23 nanard Exp $
$Id: Changelog.txt,v 1.345 2013/06/13 13:21:28 nanard Exp $
2013/12/13:
Make all manufacturer info configurable thanks to Leo Moll
2013/06/13:
Have 3 UUID for the 3 devices (IGD, WAN Device, WAN Connection Device)
2013/06/06:
update upnpreplyparse to allow larger values (128 chars instead of 64)
2013/06/05:
check Service ID in SetDefaultConnectionService method
Don't advertise WANPPPConnection in UPNP_STRICT mode
2013/05/29:
Remove namespace from variable name elements in Events "propertyset"
to comply with UPNP DeviceArchitecture v1.1.
2013/05/20:
Adding support for IP Filter version 5.x
2013/05/16:
refuses non integer <NewPortMappingIndex> values
2013/05/14:
Update upnpreplyparse to take into account "empty" elements
2013/05/03:
Use pkg-config under linux to find libiptc. Thanks to Olivier Langlois
2013/04/29:
Add warning message when using IPv4 address for listening_ip with IPv6 enabled
2013/04/27:
Uses ifr_addr if ifr_netmask is not defined in struct ifreq
2013/04/26:
Correctly handle truncated snprintf() in SSDP code
2013/04/24:
to avoid build race conditions, genconfig.sh now uses a temporary file
2013/04/20:
use scope in get_lan_for_peer() for IPv6 addresses
2013/03/23:
autodetect LAN interface netmask instead of defaulting to /24
2013/02/11:
Use $(DESTDIR) in Makefile.linux.
see https://github.com/miniupnp/miniupnp/issues/26
2013/02/07:
Add DATE: header in SSDP packets

View File

@ -1,5 +1,5 @@
MiniUPnP project.
(c) 2006-2012 Thomas Bernard
(c) 2006-2013 Thomas Bernard
Homepage : http://miniupnp.free.fr/
Mirror: http://miniupnp.tuxfamily.org/
github: https://github.com/miniupnp/miniupnp
@ -74,8 +74,6 @@ To Build and install :
> make -f Makefile.linux
If not using iptables from your system,
> IPTABLESPATH=/path/to/iptables-1.4.1 make -f Makefile.linux
note : make sure you have iptables with static libraries compiled.
use "./configure --enable-static" before compiling iptables
- install as root using :
> make -f Makefile.linux install
- A miniupnpd script should be installed to /etc/init.d
@ -101,7 +99,7 @@ How to get libiptc with its headers on debian :
> ./configure --enable-static
> make
- it is now possible to compile miniupnpd using the following command :
> IPTABLESPATH=§path/to/iptables-x.x.x make -f Makefile.linux
> IPTABLESPATH=/path/to/iptables-x.x.x make -f Makefile.linux
=========================== Configuration =============================
Edit the /etc/miniupnpd.conf file to set options. Almost all options are

View File

@ -1,6 +1,6 @@
# $Id: Makefile.linux,v 1.75 2012/08/24 18:09:20 nanard Exp $
# $Id: Makefile.linux,v 1.78 2013/05/03 09:30:33 nanard Exp $
# MiniUPnP project
# (c) 2006-2012 Thomas Bernard
# (c) 2006-2013 Thomas Bernard
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
# Author : Thomas Bernard
# for use with GNU Make
@ -9,11 +9,12 @@
# $ CONFIG_OPTIONS="--ipv6 --igd2" make -f Makefile.linux
#
# To install use :
# $ PREFIX=/dummyinstalldir make -f Makefile.linux install
# $ DESTDIR=/dummyinstalldir make -f Makefile.linux install
# or :
# $ INSTALLPREFIX=/usr/local make -f Makefile.linux install
# or :
# $ make -f Makefile.linux install
# (default INSTALLPREFIX is /usr)
#
# if your system hasn't iptables libiptc headers and binary correctly
# installed, you need to get iptables sources from http://netfilter.org/
@ -44,15 +45,35 @@ MANINSTALLDIR = $(INSTALLPREFIX)/share/man/man8
BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
upnpreplyparse.o minixml.o portinuse.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 pcpserver.o\
upnpevents.o upnputils.o getconnstatus.o \
upnppinhole.o
upnppinhole.o pcplearndscp.o
LNXOBJS = linux/getifstats.o linux/ifacewatcher.o linux/getroute.o
NETFILTEROBJS = netfilter/iptcrdr.o netfilter/iptpinhole.o
NETFILTEROBJS = netfilter/iptcrdr.o netfilter/iptpinhole.o netfilter/nfct_get.o
ALLOBJS = $(BASEOBJS) $(LNXOBJS) $(NETFILTEROBJS)
PCFILE_FOUND := $(shell pkg-config --exists libiptc; echo $$?)
ifeq (${PCFILE_FOUND},0)
IPTABLESVERSION := $(shell pkg-config --modversion libiptc)
IPTABLESVERSION1 := $(shell echo $(IPTABLESVERSION) | cut -d. -f1 )
IPTABLESVERSION2 := $(shell echo $(IPTABLESVERSION) | cut -d. -f2 )
IPTABLESVERSION3 := $(shell echo $(IPTABLESVERSION) | cut -d. -f3 )
# test if iptables version >= 1.4.3
TEST := $(shell [ \( \( $(IPTABLESVERSION1) -ge 1 \) -a \( $(IPTABLESVERSION2) -ge 4 \) \) -a \( $(IPTABLESVERSION3) -ge 3 \) ] && echo 1 )
ifeq ($(TEST), 1)
CFLAGS += -DIPTABLES_143
endif
CFLAGS += $(shell pkg-config --cflags libiptc)
LIBS += $(shell pkg-config --static --libs-only-l libiptc)
LDFLAGS += $(shell pkg-config --libs-only-L libiptc)
LDFLAGS += $(shell pkg-config --libs-only-other libiptc)
else
ifeq "$(wildcard /etc/gentoo-release )" ""
LIBS ?= -liptc
else # gentoo
@ -114,9 +135,17 @@ LIBS := $(LIBS) -lip6tc
endif # ($(TESTIP6TC), 1)
endif # ($(TEST), 1)
endif # ifdef IPTABLESPATH
endif # ifdef PCFILE_FOUND
LIBS += -lnfnetlink
TEST := $(shell pkg-config --atleast-version=1.0.2 libnetfilter_conntrack && pkg-config --atleast-version=1.0.3 libmnl && echo 1)
ifeq ($(TEST),1)
CFLAGS += -DUSE_NFCT
LIBS += $(shell pkg-config --static --libs-only-l libmnl)
LIBS += $(shell pkg-config --static --libs-only-l libnetfilter_conntrack)
endif # ($(TEST),1)
TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o
EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \
@ -140,21 +169,23 @@ install: miniupnpd miniupnpd.8 miniupnpd.conf genuuid \
netfilter/ip6tables_init.sh netfilter/ip6tables_removeall.sh \
linux/miniupnpd.init.d.script
$(STRIP) miniupnpd
$(INSTALL) -d $(SBININSTALLDIR)
$(INSTALL) miniupnpd $(SBININSTALLDIR)
$(INSTALL) -d $(ETCINSTALLDIR)
$(INSTALL) netfilter/iptables_init.sh $(ETCINSTALLDIR)
$(INSTALL) netfilter/iptables_removeall.sh $(ETCINSTALLDIR)
$(INSTALL) netfilter/ip6tables_init.sh $(ETCINSTALLDIR)
$(INSTALL) netfilter/ip6tables_removeall.sh $(ETCINSTALLDIR)
$(INSTALL) --mode=0644 -b miniupnpd.conf $(ETCINSTALLDIR)
$(INSTALL) -d $(PREFIX)/etc/init.d
$(INSTALL) linux/miniupnpd.init.d.script $(PREFIX)/etc/init.d/miniupnpd
$(INSTALL) miniupnpd.8 $(MANINSTALLDIR)
gzip $(MANINSTALLDIR)/miniupnpd.8
$(INSTALL) -d $(DESTDIR)$(SBININSTALLDIR)
$(INSTALL) miniupnpd $(DESTDIR)$(SBININSTALLDIR)
$(INSTALL) -d $(DESTDIR)$(ETCINSTALLDIR)
$(INSTALL) netfilter/iptables_init.sh $(DESTDIR)$(ETCINSTALLDIR)
$(INSTALL) netfilter/iptables_removeall.sh $(DESTDIR)$(ETCINSTALLDIR)
$(INSTALL) netfilter/ip6tables_init.sh $(DESTDIR)$(ETCINSTALLDIR)
$(INSTALL) netfilter/ip6tables_removeall.sh $(DESTDIR)$(ETCINSTALLDIR)
$(INSTALL) --mode=0644 -b miniupnpd.conf $(DESTDIR)$(ETCINSTALLDIR)
$(INSTALL) -d $(DESTDIR)$(PREFIX)/etc/init.d
$(INSTALL) linux/miniupnpd.init.d.script $(DESTDIR)$(PREFIX)/etc/init.d/miniupnpd
$(INSTALL) -d $(DESTDIR)$(MANINSTALLDIR)
$(INSTALL) --mode=0644 miniupnpd.8 $(DESTDIR)$(MANINSTALLDIR)
gzip $(DESTDIR)$(MANINSTALLDIR)/miniupnpd.8
# genuuid is using the uuidgen CLI tool which is part of libuuid
# from the e2fsprogs
# 'cat /proc/sys/kernel/random/uuid' could be also used
genuuid:
ifeq ($(TARGET_OPENWRT),)
sed -i -e "s/^uuid=[-0-9a-f]*/uuid=`(genuuid||uuidgen||uuid) 2>/dev/null`/" miniupnpd.conf
@ -182,7 +213,8 @@ config.h: genconfig.sh VERSION
depend: config.h
makedepend -f$(MAKEFILE_LIST) -Y \
$(ALLOBJS:.o=.c) $(TESTUPNPDESCGENOBJS:.o=.c) \
testgetifstats.c 2>/dev/null
testgetifstats.c testupnppermissions.c testgetifaddr.c \
testgetroute.c miniupnpdctl.c 2>/dev/null
# DO NOT DELETE
@ -203,14 +235,15 @@ 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
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 portinuse.h
upnpredirect.o: netfilter/iptcrdr.h commonrdr.h
getifaddr.o: config.h getifaddr.h
daemonize.o: daemonize.h config.h
upnpglobalvars.o: config.h upnpglobalvars.h upnppermissions.h
upnpglobalvars.o: miniupnpdtypes.h
upnpglobalvars.o: miniupnpdtypes.h upnpdescstrings.h
options.o: config.h options.h upnppermissions.h upnpglobalvars.h
options.o: miniupnpdtypes.h
upnppermissions.o: config.h upnppermissions.h
@ -220,13 +253,17 @@ minissdp.o: upnputils.h getroute.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: portinuse.h
pcpserver.o: config.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
upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h
upnputils.o: miniupnpdtypes.h
getconnstatus.o: getconnstatus.h getifaddr.h
upnppinhole.o: macros.h config.h upnpredirect.h upnpglobalvars.h
upnppinhole.o: upnppermissions.h miniupnpdtypes.h upnpevents.h
upnppinhole.o: netfilter/iptpinhole.h
pcplearndscp.o: config.h upnpglobalvars.h upnppermissions.h miniupnpdtypes.h
pcplearndscp.o: pcplearndscp.h
linux/getifstats.o: config.h getifstats.h
linux/ifacewatcher.o: config.h ifacewatcher.h config.h minissdp.h
linux/ifacewatcher.o: miniupnpdtypes.h getifaddr.h upnpglobalvars.h
@ -237,8 +274,13 @@ netfilter/iptcrdr.o: config.h upnpglobalvars.h upnppermissions.h
netfilter/iptcrdr.o: miniupnpdtypes.h
netfilter/iptpinhole.o: config.h netfilter/iptpinhole.h upnpglobalvars.h
netfilter/iptpinhole.o: upnppermissions.h config.h miniupnpdtypes.h
testupnpdescgen.o: macros.h config.h upnpdescgen.h
testupnpdescgen.o: macros.h config.h upnpdescgen.h upnpdescstrings.h
upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h
upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h
upnpdescgen.o: miniupnpdtypes.h upnpdescstrings.h upnpurns.h getconnstatus.h
testgetifstats.o: getifstats.h
testupnppermissions.o: upnppermissions.h config.h
testgetifaddr.o: getifaddr.h
testgetroute.o: getroute.h upnputils.h upnpglobalvars.h upnppermissions.h
testgetroute.o: config.h miniupnpdtypes.h
miniupnpdctl.o: macros.h

View File

@ -1,8 +1,8 @@
#! /bin/sh
# $Id: genconfig.sh,v 1.61 2012/10/03 21:07:29 nanard Exp $
# $Id: genconfig.sh,v 1.63 2013/05/03 09:30:10 nanard Exp $
# miniupnp daemon
# http://miniupnp.free.fr or http://miniupnp.tuxfamily.org/
# (c) 2006-2012 Thomas Bernard
# (c) 2006-2013 Thomas Bernard
# This software is subject to the conditions detailed in the
# LICENCE file provided within the distribution
@ -12,12 +12,19 @@ case "$argv" in
--igd2) IGD2=1 ;;
--strict) STRICT=1 ;;
--leasefile) LEASEFILE=1 ;;
--pcp) PCP=1 ;;
--pcp-peer)
PCP=1
PCP_PEER=1
;;
--help|-h)
echo "Usage : $0 [options]"
echo " --ipv6 enable IPv6"
echo " --igd2 build an IGDv2 instead of an IGDv1"
echo " --strict be more strict regarding compliance with UPnP specifications"
echo " --leasefile enable lease file"
echo " --pcp enable PCP"
echo " --pcp-peer enable PCP PEER operation"
exit 1
;;
*)
@ -29,7 +36,9 @@ esac
done
RM="rm -f"
CONFIGFILE="config.h"
MV="mv"
CONFIGFILE="config.h.tmp"
CONFIGFILE_FINAL="config.h"
CONFIGMACRO="CONFIG_H_INCLUDED"
# version reported in XML descriptions
@ -72,7 +81,7 @@ ${RM} ${CONFIGFILE}
echo "/* MiniUPnP Project" >> ${CONFIGFILE}
echo " * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/" >> ${CONFIGFILE}
echo " * (c) 2006-2012 Thomas Bernard" >> ${CONFIGFILE}
echo " * (c) 2006-2013 Thomas Bernard" >> ${CONFIGFILE}
echo " * generated by $0 on `date`" >> ${CONFIGFILE}
echo " * using command line options $* */" >> ${CONFIGFILE}
echo "#ifndef $CONFIGMACRO" >> ${CONFIGFILE}
@ -230,6 +239,10 @@ case $OS_NAME in
Gentoo)
OS_URL=http://www.gentoo.org/
;;
arch)
OS_URL=http://www.archlinux.org/
OS_VERSION=`uname -r`
;;
esac
fi
echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE}
@ -319,6 +332,31 @@ echo "/* Comment the following line to disable NAT-PMP operations */" >> ${CONFI
echo "#define ENABLE_NATPMP" >> ${CONFIGFILE}
echo "" >> ${CONFIGFILE}
if [ -n "$PCP" ]; then
echo "/* Comment the following line to disable PCP operations */" >> ${CONFIGFILE}
echo "#define ENABLE_PCP" >> ${CONFIGFILE}
echo "" >> ${CONFIGFILE}
else
echo "/* Uncomment the following line to enable PCP operations */" >> ${CONFIGFILE}
echo "/*#define ENABLE_PCP*/" >> ${CONFIGFILE}
echo "" >> ${CONFIGFILE}
fi
echo "#ifdef ENABLE_PCP" >> ${CONFIGFILE}
if [ -n "$PCP_PEER" ]; then
echo "/* Comment the following line to disable PCP PEER operation */" >> ${CONFIGFILE}
echo "#define PCP_PEER" >> ${CONFIGFILE}
else
echo "/* Uncomment the following line to enable PCP PEER operation */" >> ${CONFIGFILE}
echo "/*#define PCP_PEER*/" >> ${CONFIGFILE}
fi
echo "#ifdef PCP_PEER" >> ${CONFIGFILE}
echo "/*#define PCP_FLOWP*/" >> ${CONFIGFILE}
echo "#endif //PCP_PEER" >> ${CONFIGFILE}
echo "/*#define PCP_SADSCP*/" >> ${CONFIGFILE}
echo "#endif //ENABLE_PCP" >> ${CONFIGFILE}
echo "" >> ${CONFIGFILE}
echo "/* Uncomment the following line to enable generation of" >> ${CONFIGFILE}
echo " * filter rules with pf */" >> ${CONFIGFILE}
echo "/*#define PF_ENABLE_FILTER_RULES*/">> ${CONFIGFILE}
@ -422,6 +460,12 @@ echo "/* disable reading and parsing of config file (miniupnpd.conf) */" >> ${CO
echo "/*#define DISABLE_CONFIG_FILE*/" >> ${CONFIGFILE}
echo "" >> ${CONFIGFILE}
echo "/* Unable the ability to configure all manufacturer infos through miniupnpd.conf */" >> ${CONFIGFILE}
echo "/*#define ENABLE_MANUFACTURER_INFO_CONFIGURATION*/" >> ${CONFIGFILE}
echo "" >> ${CONFIGFILE}
echo "#endif" >> ${CONFIGFILE}
${MV} ${CONFIGFILE} ${CONFIGFILE_FINAL}
exit 0

View File

@ -1,7 +1,7 @@
/* $Id: getconnstatus.c,v 1.4 2011/05/23 20:22:41 nanard Exp $ */
/* $Id: getconnstatus.c,v 1.6 2013/03/23 10:46:54 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011 Thomas Bernard
* (c) 2011-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -35,7 +35,7 @@ get_wan_connection_status(const char * ifname)
/* we need a better implementation here.
* I'm afraid it should be device specific */
r = getifaddr(ifname, addr, INET_ADDRSTRLEN);
r = getifaddr(ifname, addr, INET_ADDRSTRLEN, NULL, NULL);
return (r < 0) ? STATUS_DISCONNECTED : STATUS_CONNECTED;
}

View File

@ -1,7 +1,7 @@
/* $Id: getifaddr.c,v 1.14 2012/02/07 11:05:07 nanard Exp $ */
/* $Id: getifaddr.c,v 1.17 2013/04/27 15:40:09 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -21,12 +21,13 @@
#include "config.h"
#include "getifaddr.h"
#if defined(USE_GETIFADDRS) || defined(ENABLE_IPV6)
#if defined(USE_GETIFADDRS) || defined(ENABLE_IPV6) || defined(ENABLE_PCP)
#include <ifaddrs.h>
#endif
int
getifaddr(const char * ifname, char * buf, int len)
getifaddr(const char * ifname, char * buf, int len,
struct in_addr * addr, struct in_addr * mask)
{
#ifndef USE_GETIFADDRS
/* use ioctl SIOCGIFADDR. Works only for ip v4 */
@ -34,7 +35,7 @@ getifaddr(const char * ifname, char * buf, int len)
int s;
struct ifreq ifr;
int ifrlen;
struct sockaddr_in * addr;
struct sockaddr_in * ifaddr;
ifrlen = sizeof(ifr);
if(!ifname || ifname[0]=='\0')
@ -52,13 +53,29 @@ getifaddr(const char * ifname, char * buf, int len)
close(s);
return -1;
}
addr = (struct sockaddr_in *)&ifr.ifr_addr;
if(!inet_ntop(AF_INET, &addr->sin_addr, buf, len))
ifaddr = (struct sockaddr_in *)&ifr.ifr_addr;
if(addr) *addr = ifaddr->sin_addr;
if(!inet_ntop(AF_INET, &ifaddr->sin_addr, buf, len))
{
syslog(LOG_ERR, "inet_ntop(): %m");
close(s);
return -1;
}
if(mask)
{
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if(ioctl(s, SIOCGIFNETMASK, &ifr, &ifrlen) < 0)
{
syslog(LOG_ERR, "ioctl(s, SIOCGIFNETMASK, ...): %m");
close(s);
return -1;
}
#ifdef ifr_netmask
*mask = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr;
#else
*mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
#endif
}
close(s);
#else /* ifndef USE_GETIFADDRS */
/* Works for all address families (both ip v4 and ip v6) */
@ -85,6 +102,8 @@ getifaddr(const char * ifname, char * buf, int len)
inet_ntop(ife->ifa_addr->sa_family,
&((struct sockaddr_in *)ife->ifa_addr)->sin_addr,
buf, len);
if(addr) *addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr;
if(mask) *mask = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr;
break;
/*
case AF_INET6:
@ -99,6 +118,56 @@ getifaddr(const char * ifname, char * buf, int len)
return 0;
}
#ifdef ENABLE_PCP
int getifaddr_in6(const char * ifname, struct in6_addr * addr){
struct ifaddrs * ifap;
struct ifaddrs * ife;
if(!ifname || ifname[0]=='\0')
return -1;
if(getifaddrs(&ifap)<0)
{
syslog(LOG_ERR, "getifaddrs: %m");
return -1;
}
for(ife = ifap; ife; ife = ife->ifa_next)
{
int found = 0;
/* skip other interfaces if one was specified */
if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
continue;
if(ife->ifa_addr == NULL)
continue;
switch(ife->ifa_addr->sa_family)
{
case AF_INET:
addr->s6_addr32[0]=0;
addr->s6_addr32[1]=0;
addr->s6_addr32[2]=htonl(0xffff);
addr->s6_addr32[3]=((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr;
//inet_ntop(ife->ifa_addr->sa_family,
// &((struct sockaddr_in *)ife->ifa_addr)->sin_addr,
// buf, len);
found = 1;
break;
case AF_INET6:
if(!IN6_IS_ADDR_LOOPBACK(&addr->s6_addr32)
&& !IN6_IS_ADDR_LINKLOCAL(&addr->s6_addr32)) {
memcpy(addr->s6_addr32, &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr, sizeof(addr->s6_addr32));
found = 1;
}
break;
}
if (found) {
break;
}
}
freeifaddrs(ifap);
return 0;
}
#endif
#ifdef ENABLE_IPV6
int
find_ipv6_addr(const char * ifname,

View File

@ -1,19 +1,26 @@
/* $Id: getifaddr.h,v 1.5 2011/05/15 08:59:27 nanard Exp $ */
/* $Id: getifaddr.h,v 1.8 2013/03/23 10:46:54 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef GETIFADDR_H_INCLUDED
#define GETIFADDR_H_INCLUDED
struct in_addr;
struct in6_addr;
/* getifaddr()
* take a network interface name and write the
* ip v4 address as text in the buffer
* returns: 0 success, -1 failure */
int
getifaddr(const char * ifname, char * buf, int len);
getifaddr(const char * ifname, char * buf, int len,
struct in_addr * addr, struct in_addr * mask);
int
getifaddr_in6(const char * ifname, struct in6_addr* addr);
/* find a non link local IP v6 address for the interface.
* if ifname is NULL, look for all interfaces */

View File

@ -1,4 +1,4 @@
/* $Id: ipfrdr.c,v 1.11 2009/10/10 18:34:39 nanard Exp $ */
/* $Id: ipfrdr.c,v 1.16 2013/05/20 00:07:47 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2007 Darren Reed
@ -243,33 +243,64 @@ add_redirect_rule2(const char * ifname, const char * rhost,
memset(&ipnat, 0, sizeof(ipnat));
ipnat.in_redir = NAT_REDIRECT;
#if IPFILTER_VERSION >= 5000000
ipnat.in_pr[0] = proto;
ipnat.in_pr[1] = proto;
#else
ipnat.in_p = proto;
#endif
if (proto == IPPROTO_TCP)
ipnat.in_flags = IPN_TCP;
if (proto == IPPROTO_UDP)
ipnat.in_flags = IPN_UDP;
ipnat.in_dcmp = FR_EQUAL;
#if IPFILTER_VERSION >= 5000000
ipnat.in_dpmin = htons(eport);
ipnat.in_dpmax = htons(eport);
ipnat.in_dpnext = htons(iport);
ipnat.in_v[0] = 4;
ipnat.in_v[1] = 4;
#else
ipnat.in_pmin = htons(eport);
ipnat.in_pmax = htons(eport);
ipnat.in_pnext = htons(iport);
ipnat.in_v = 4;
#endif
strlcpy(ipnat.in_tag.ipt_tag, group_name, IPFTAG_LEN);
#ifdef USE_IFNAME_IN_RULES
if (ifname) {
#if IPFILTER_VERSION >= 5000000
/* XXX check for stack overflow ! */
ipnat.in_ifnames[0] = 0;
ipnat.in_ifnames[1] = 0;
strlcpy(ipnat.in_names, ifname, IFNAMSIZ);
ipnat.in_namelen = strlen(ipnat.in_names) + 1;
#else
strlcpy(ipnat.in_ifnames[0], ifname, IFNAMSIZ);
strlcpy(ipnat.in_ifnames[1], ifname, IFNAMSIZ);
#endif
}
#endif
if(rhost && rhost[0] != '\0' && rhost[0] != '*')
{
#if IPFILTER_VERSION >= 5000000
inet_pton(AF_INET, rhost, &ipnat.in_nsrc.na_addr[0].in4); /* in_nsrcip */
ipnat.in_nsrc.na_addr[1].in4.s_addr = 0xffffffff; /* in_nsrcmsk */
#else
inet_pton(AF_INET, rhost, &ipnat.in_src[0].in4);
ipnat.in_src[1].in4.s_addr = 0xffffffff;
#endif
}
#if IPFILTER_VERSION >= 5000000
inet_pton(AF_INET, iaddr, &ipnat.in_ndst.na_addr[0].in4); /* in_ndstip */
ipnat.in_ndst.na_addr[1].in4.s_addr = 0xffffffff; /* in_ndstmsk */
#else
inet_pton(AF_INET, iaddr, &ipnat.in_in[0].in4);
ipnat.in_in[1].in4.s_addr = 0xffffffff;
#endif
obj.ipfo_rev = IPFILTER_VERSION;
obj.ipfo_size = sizeof(ipnat);
@ -323,10 +354,17 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
syslog(LOG_ERR, "ioctl(dev, SIOCGENITER): %m");
break;
}
#if IPFILTER_VERSION >= 5000000
if (eport == ntohs(ipn.in_dpmin) &&
eport == ntohs(ipn.in_dpmax) &&
strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
ipn.in_pr[0] == proto)
#else
if (eport == ntohs(ipn.in_pmin) &&
eport == ntohs(ipn.in_pmax) &&
strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
ipn.in_p == proto)
#endif
{
strlcpy(desc, "", desclen);
if (packets != NULL)
@ -334,12 +372,24 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
if (bytes != NULL)
*bytes = 0;
if (iport != NULL)
#if IPFILTER_VERSION >= 5000000
*iport = ntohs(ipn.in_dpnext);
#else
*iport = ntohs(ipn.in_pnext);
#endif
if ((desc != NULL) && (timestamp != NULL))
get_redirect_desc(eport, proto, desc, desclen, timestamp);
if ((rhost != NULL) && (rhostlen > 0))
#if IPFILTER_VERSION >= 5000000
inet_ntop(AF_INET, &ipn.in_nsrc.na_addr[0].in4, rhost, rhostlen); /* in_nsrcip */
#else
inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen);
#endif
#if IPFILTER_VERSION >= 5000000
inet_ntop(AF_INET, &ipn.in_ndst.na_addr[0].in4, iaddr, iaddrlen); /* in_ndstip */
#else
inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
#endif
r = 0;
}
} while (ipn.in_next != NULL);
@ -394,12 +444,22 @@ get_redirect_rule_by_index(int index,
continue;
if (index == n++) {
#if IPFILTER_VERSION >= 5000000
*proto = ipn.in_pr[0];
*eport = ntohs(ipn.in_dpmax);
*iport = ntohs(ipn.in_dpnext);
#else
*proto = ipn.in_p;
*eport = ntohs(ipn.in_pmax);
*iport = ntohs(ipn.in_pnext);
#endif
if (ifname)
#if IPFILTER_VERSION >= 5000000
strlcpy(ifname, ipn.in_names + ipn.in_ifnames[0], IFNAMSIZ);
#else
strlcpy(ifname, ipn.in_ifnames[0], IFNAMSIZ);
#endif
if (packets != NULL)
*packets = 0;
if (bytes != NULL)
@ -407,8 +467,16 @@ get_redirect_rule_by_index(int index,
if ((desc != NULL) && (timestamp != NULL))
get_redirect_desc(*eport, *proto, desc, desclen, timestamp);
if ((rhost != NULL) && (rhostlen > 0))
#if IPFILTER_VERSION >= 5000000
inet_ntop(AF_INET, &ipn.in_nsrc.na_addr[0].in4, rhost, rhostlen); /* in_nsrcip */
#else
inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen);
#endif
#if IPFILTER_VERSION >= 5000000
inet_ntop(AF_INET, &ipn.in_ndst.na_addr[0].in4, iaddr, iaddrlen); /* in_ndstip */
#else
inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
#endif
r = 0;
}
} while (ipn.in_next != NULL);
@ -447,10 +515,17 @@ real_delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
"delete_redirect_rule");
break;
}
#if IPFILTER_VERSION >= 5000000
if (eport == ntohs(ipn.in_dpmin) &&
eport == ntohs(ipn.in_dpmax) &&
strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
ipn.in_pr[0] == proto)
#else
if (eport == ntohs(ipn.in_pmin) &&
eport == ntohs(ipn.in_pmax) &&
strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
ipn.in_p == proto)
#endif
{
obj.ipfo_rev = IPFILTER_VERSION;
obj.ipfo_size = sizeof(ipn);
@ -504,7 +579,11 @@ add_filter_rule2(const char * ifname, const char * rhost,
fr.fr_flags = FR_PASS|FR_KEEPSTATE|FR_QUICK|FR_INQUE;
if (GETFLAG(LOGPACKETSMASK))
fr.fr_flags |= FR_LOG|FR_LOGFIRST;
#if IPFILTER_VERSION >= 5000000
fr.fr_family = PF_INET;
#else
fr.fr_v = 4;
#endif
fr.fr_type = FR_T_IPF;
fr.fr_dun.fru_ipf = &ipffr;
@ -516,10 +595,25 @@ add_filter_rule2(const char * ifname, const char * rhost,
fr.fr_dcmp = FR_EQUAL;
fr.fr_dport = eport;
#ifdef USE_IFNAME_IN_RULES
if (ifname)
if (ifname) {
#if IPFILTER_VERSION >= 5000000
/* XXX check for stack overflow ! */
fr.fr_ifnames[0] = fr.fr_namelen;
strlcpy(fr.fr_names + fr.fr_ifnames[0], ifname, IFNAMSIZ);
fr.fr_namelen += strlen(ifname) + 1;
#else
strlcpy(fr.fr_ifnames[0], ifname, IFNAMSIZ);
#endif
}
#endif
#if IPFILTER_VERSION >= 5000000
/* XXX check for stack overflow ! */
fr.fr_group = fr.fr_namelen;
strlcpy(fr.fr_names + fr.fr_group, group_name, FR_GROUPLEN);
fr.fr_namelen += strlen(group_name) + 1;
#else
strlcpy(fr.fr_group, group_name, sizeof(fr.fr_group));
#endif
if (proto == IPPROTO_TCP) {
fr.fr_tcpf = TH_SYN;
@ -671,10 +765,17 @@ get_portmappings_in_range(unsigned short startport, unsigned short endport,
if (strcmp(ipn.in_tag.ipt_tag, group_name) != 0)
continue;
#if IPFILTER_VERSION >= 5000000
eport = ntohs(ipn.in_dpmin);
if( (eport == ntohs(ipn.in_dpmax))
&& (ipn.in_pr[0] == proto)
&& (startport <= eport) && (eport <= endport) )
#else
eport = ntohs(ipn.in_pmin);
if( (eport == ntohs(ipn.in_pmax))
&& (ipn.in_p == proto)
&& (startport <= eport) && (eport <= endport) )
#endif
{
if(*number >= capacity)
{

View File

@ -1,7 +1,7 @@
/* $Id: getifstats.c,v 1.11 2012/04/06 15:26:45 nanard Exp $ */
/* $Id: getifstats.c,v 1.12 2013/04/29 10:18:20 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -14,6 +14,16 @@
#include "../config.h"
#include "../getifstats.h"
#ifdef GET_WIRELESS_STATS
#include <unistd.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <linux/wireless.h>
#endif /* GET_WIRELESS_STATS */
/* that is the answer */
#define BAUDRATE_DEFAULT 4200000
int
getifstats(const char * ifname, struct ifdata * data)
{
@ -27,10 +37,10 @@ getifstats(const char * ifname, struct ifdata * data)
static time_t cache_timestamp = 0;
static struct ifdata cache_data;
time_t current_time;
#endif
#endif /* ENABLE_GETIFSTATS_CACHING */
if(!data)
return -1;
data->baudrate = 4200000; /* that is the answer */
data->baudrate = BAUDRATE_DEFAULT;
data->opackets = 0;
data->ipackets = 0;
data->obytes = 0;
@ -48,7 +58,7 @@ getifstats(const char * ifname, struct ifdata * data)
return 0;
}
}
#endif
#endif /* ENABLE_GETIFSTATS_CACHING */
f = fopen("/proc/net/dev", "r");
if(!f) {
syslog(LOG_ERR, "getifstats() : cannot open /proc/net/dev : %m");
@ -99,13 +109,27 @@ getifstats(const char * ifname, struct ifdata * data)
} else {
syslog(LOG_WARNING, "cannot read %s file : %m", fname);
}
#ifdef GET_WIRELESS_STATS
if(data->baudrate == BAUDRATE_DEFAULT) {
struct iwreq iwr;
int s;
s = socket(AF_INET, SOCK_DGRAM, 0);
if(s >= 0) {
strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
if(ioctl(s, SIOCGIWRATE, &iwr) >= 0) {
data->baudrate = iwr.u.bitrate.value;
}
close(s);
}
}
#endif /* GET_WIRELESS_STATS */
#ifdef ENABLE_GETIFSTATS_CACHING
if(r==0 && current_time!=((time_t)-1)) {
/* cache the new data */
cache_timestamp = current_time;
memcpy(&cache_data, data, sizeof(struct ifdata));
}
#endif
#endif /* ENABLE_GETIFSTATS_CACHING */
return r;
}

View File

@ -1,4 +1,4 @@
/* $Id: minissdp.c,v 1.48 2013/02/07 12:22:25 nanard Exp $ */
/* $Id: minissdp.c,v 1.54 2013/06/15 12:50:10 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
@ -313,12 +313,17 @@ USN:uuid:upnp-InternetGatewayDevice-1_0-0090a2777777::upnp:rootdevice
EXT:
*/
/* not really an SSDP "announce" as it is the response
* to a SSDP "M-SEARCH" */
/* Responds to a SSDP "M-SEARCH"
* s : socket to use
* addr : peer
* st, st_len : ST: header
* suffix : suffix for USN: header
* host, port : our HTTP host, port
*/
static void
SendSSDPAnnounce2(int s, const struct sockaddr * addr,
const char * st, int st_len, const char * suffix,
const char * host, unsigned short port)
SendSSDPResponse(int s, const struct sockaddr * addr,
const char * st, int st_len, const char * suffix,
const char * host, unsigned short port, const char * uuidvalue)
{
int l, n;
char buf[512];
@ -369,6 +374,18 @@ SendSSDPAnnounce2(int s, const struct sockaddr * addr,
st_is_uuid ? 0 : st_len, st, suffix,
host, (unsigned int)port,
upnp_bootid, upnp_bootid, upnp_configid);
if(l<0)
{
syslog(LOG_ERR, "%s: snprintf failed %m",
"SendSSDPResponse()");
return;
}
else if((unsigned)l>=sizeof(buf))
{
syslog(LOG_WARNING, "%s: truncated output",
"SendSSDPResponse()");
l = sizeof(buf) - 1;
}
addrlen = (addr->sa_family == AF_INET6)
? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
n = sendto(s, buf, l, 0,
@ -395,22 +412,28 @@ SendSSDPAnnounce2(int s, const struct sockaddr * addr,
static struct {
const char * s;
const int version;
const char * uuid;
} const known_service_types[] =
{
{"upnp:rootdevice", 0},
{"urn:schemas-upnp-org:device:InternetGatewayDevice:", IGD_VER},
{"urn:schemas-upnp-org:device:WANConnectionDevice:", 1},
{"urn:schemas-upnp-org:device:WANDevice:", 1},
{"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:", 1},
{"urn:schemas-upnp-org:service:WANIPConnection:", WANIPC_VER},
{"urn:schemas-upnp-org:service:WANPPPConnection:", 1},
{"upnp:rootdevice", 0, uuidvalue_igd},
{"urn:schemas-upnp-org:device:InternetGatewayDevice:", IGD_VER, uuidvalue_igd},
{"urn:schemas-upnp-org:device:WANConnectionDevice:", 1, uuidvalue_wcd},
{"urn:schemas-upnp-org:device:WANDevice:", 1, uuidvalue_wan},
{"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:", 1, uuidvalue_wan},
{"urn:schemas-upnp-org:service:WANIPConnection:", WANIPC_VER, uuidvalue_wcd},
#ifndef UPNP_STRICT
/* We use WAN IP Connection, not PPP connection,
* but buggy control points may try to use WanPPPConnection
* anyway */
{"urn:schemas-upnp-org:service:WANPPPConnection:", 1, uuidvalue_wcd},
#endif
#ifdef ENABLE_L3F_SERVICE
{"urn:schemas-upnp-org:service:Layer3Forwarding:", 1},
{"urn:schemas-upnp-org:service:Layer3Forwarding:", 1, uuidvalue_igd},
#endif
#ifdef ENABLE_6FC_SERVICE
{"url:schemas-upnp-org:service:WANIPv6FirewallControl:", 1},
{"url:schemas-upnp-org:service:WANIPv6FirewallControl:", 1, uuidvalue_wcd},
#endif
{0, 0}
{0, 0, 0}
};
static void
@ -446,13 +469,13 @@ SendSSDPNotify(int s, const struct sockaddr * dest,
upnp_bootid, upnp_bootid, upnp_configid );
if(l<0)
{
syslog(LOG_ERR, "SendSSDPNotifies() snprintf error");
syslog(LOG_ERR, "SendSSDPNotify() snprintf error");
return;
}
else if((unsigned int)l >= sizeof(bufr))
{
syslog(LOG_WARNING, "SendSSDPNotifies(): truncated output");
l = sizeof(bufr);
syslog(LOG_WARNING, "SendSSDPNotify(): truncated output");
l = sizeof(bufr) - 1;
}
n = sendto(s, bufr, l, 0, dest,
#ifdef ENABLE_IPV6
@ -511,13 +534,17 @@ SendSSDPNotifies(int s, const char * host, unsigned short port,
snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version);
SendSSDPNotify(s, (struct sockaddr *)&sockname, host, port,
known_service_types[i].s, ver_str, /* NT: */
uuidvalue, "::", known_service_types[i].s, /* ver_str, USN: */
known_service_types[i].uuid, "::",
known_service_types[i].s, /* ver_str, USN: */
lifetime, ipv6);
if(i==0) /* rootdevice */
if(0==memcmp(known_service_types[i].s,
"urn:schemas-upnp-org:device", sizeof("urn:schemas-upnp-org:device")-1))
{
SendSSDPNotify(s, (struct sockaddr *)&sockname, host, port,
uuidvalue, "", /* NT: */
uuidvalue, "", "", /* ver_str, USN: */
known_service_types[i].uuid, "", /* NT: */
known_service_types[i].uuid, "", "", /* ver_str, USN: */
lifetime, ipv6);
}
i++;
}
}
@ -727,9 +754,10 @@ ProcessSSDPData(int s, const char *bufr, int n,
)
{
syslog(LOG_INFO, "Single search found");
SendSSDPAnnounce2(s, sender,
st, st_len, "",
announced_host, port);
SendSSDPResponse(s, sender,
st, st_len, "",
announced_host, port,
known_service_types[i].uuid);
break;
}
}
@ -745,21 +773,41 @@ ProcessSSDPData(int s, const char *bufr, int n,
else
snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version);
l = (int)strlen(known_service_types[i].s);
SendSSDPAnnounce2(s, sender,
known_service_types[i].s, l, ver_str,
announced_host, port);
SendSSDPResponse(s, sender,
known_service_types[i].s, l, ver_str,
announced_host, port,
known_service_types[i].uuid);
}
/* also answer for uuid */
SendSSDPAnnounce2(s, sender, uuidvalue, strlen(uuidvalue), "",
announced_host, port);
SendSSDPResponse(s, sender, uuidvalue_igd, strlen(uuidvalue_igd), "",
announced_host, port, uuidvalue_igd);
SendSSDPResponse(s, sender, uuidvalue_wan, strlen(uuidvalue_wan), "",
announced_host, port, uuidvalue_wan);
SendSSDPResponse(s, sender, uuidvalue_wcd, strlen(uuidvalue_wcd), "",
announced_host, port, uuidvalue_wcd);
}
/* responds to request by UUID value */
l = (int)strlen(uuidvalue);
if(l==st_len && (0 == memcmp(st, uuidvalue, l)))
l = (int)strlen(uuidvalue_igd);
if(l==st_len)
{
syslog(LOG_INFO, "ssdp:uuid found");
SendSSDPAnnounce2(s, sender, st, st_len, "",
announced_host, port);
if(0 == memcmp(st, uuidvalue_igd, l))
{
syslog(LOG_INFO, "ssdp:uuid (IGD) found");
SendSSDPResponse(s, sender, st, st_len, "",
announced_host, port, uuidvalue_igd);
}
else if(0 == memcmp(st, uuidvalue_wan, l))
{
syslog(LOG_INFO, "ssdp:uuid (WAN) found");
SendSSDPResponse(s, sender, st, st_len, "",
announced_host, port, uuidvalue_wan);
}
else if(0 == memcmp(st, uuidvalue_wcd, l))
{
syslog(LOG_INFO, "ssdp:uuid (WCD) found");
SendSSDPResponse(s, sender, st, st_len, "",
announced_host, port, uuidvalue_wcd);
}
}
}
else
@ -806,7 +854,7 @@ SendSSDPbyebye(int s, const struct sockaddr * dest,
else if((unsigned int)l >= sizeof(bufr))
{
syslog(LOG_WARNING, "SendSSDPbyebye(): truncated output");
l = sizeof(bufr);
l = sizeof(bufr) - 1;
}
n = sendto(s, bufr, l, 0, dest,
#ifdef ENABLE_IPV6
@ -871,9 +919,11 @@ SendSSDPGoodbye(int * sockets, int n_sockets)
(struct sockaddr *)&sockname,
#endif
known_service_types[i].s, ver_str, /* NT: */
uuidvalue, "::", known_service_types[i].s, /* ver_str, USN: */
known_service_types[i].uuid, "::",
known_service_types[i].s, /* ver_str, USN: */
ipv6);
if(i==0) /* root device */
if(0==memcmp(known_service_types[i].s,
"urn:schemas-upnp-org:device", sizeof("urn:schemas-upnp-org:device")-1))
{
ret += SendSSDPbyebye(sockets[j],
#ifdef ENABLE_IPV6
@ -881,8 +931,8 @@ SendSSDPGoodbye(int * sockets, int n_sockets)
#else
(struct sockaddr *)&sockname,
#endif
uuidvalue, "", /* NT: */
uuidvalue, "", "", /* ver_str, USN: */
known_service_types[i].uuid, "", /* NT: */
known_service_types[i].uuid, "", "", /* ver_str, USN: */
ipv6);
}
}
@ -932,7 +982,13 @@ SubmitServicesToMiniSSDPD(const char * host, unsigned short port) {
else
snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version);
l = snprintf(strbuf, sizeof(strbuf), "%s::%s%s",
uuidvalue, known_service_types[i].s, ver_str);
known_service_types[i].uuid, known_service_types[i].s, ver_str);
if(l<0) {
syslog(LOG_WARNING, "SubmitServicesToMiniSSDPD: snprintf %m");
continue;
} else if((unsigned)l>=sizeof(strbuf)) {
l = sizeof(strbuf) - 1;
}
CODELENGTH(l, p);
memcpy(p, strbuf, l);
p += l;
@ -942,6 +998,12 @@ SubmitServicesToMiniSSDPD(const char * host, unsigned short port) {
p += l;
l = snprintf(strbuf, sizeof(strbuf), "http://%s:%u" ROOTDESC_PATH,
host, (unsigned int)port);
if(l<0) {
syslog(LOG_WARNING, "SubmitServicesToMiniSSDPD: snprintf %m");
continue;
} else if((unsigned)l>=sizeof(strbuf)) {
l = sizeof(strbuf) - 1;
}
CODELENGTH(l, p);
memcpy(p, strbuf, l);
p += l;

View File

@ -1,4 +1,4 @@
/* $Id: miniupnpd.c,v 1.173 2013/02/06 10:50:04 nanard Exp $ */
/* $Id: miniupnpd.c,v 1.176 2013/06/13 13:21:29 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
@ -65,6 +65,11 @@
#include "upnpevents.h"
#ifdef ENABLE_NATPMP
#include "natpmp.h"
#ifdef ENABLE_PCP
#include "pcpserver.h"
#else
#define PCP_MAX_LEN 32
#endif
#endif
#include "commonrdr.h"
#include "upnputils.h"
@ -561,7 +566,8 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str)
/* not starting with a digit : suppose it is an interface name */
memcpy(lan_addr->ifname, str, n);
lan_addr->ifname[n] = '\0';
if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str)) < 0)
if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str),
&lan_addr->addr, &lan_addr->mask) < 0)
goto parselan_error;
}
else
@ -570,9 +576,9 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str)
goto parselan_error;
memcpy(lan_addr->str, str, n);
lan_addr->str[n] = '\0';
if(!inet_aton(lan_addr->str, &lan_addr->addr))
goto parselan_error;
}
if(!inet_aton(lan_addr->str, &lan_addr->addr))
goto parselan_error;
if(*p == '/')
{
const char * q = ++p;
@ -598,7 +604,7 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str)
lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0);
}
}
else
else if(lan_addr->mask.s_addr == 0)
{
/* by default, networks are /24 */
lan_addr->mask.s_addr = htonl(0xffffff00u);
@ -630,6 +636,10 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str)
fprintf(stderr, "Cannot get index for network interface %s",
lan_addr->ifname);
}
else
{
fprintf(stderr, "Warning: please specify LAN network interface by name instead of IPv4 address\n");
}
#endif
return 0;
parselan_error:
@ -638,6 +648,35 @@ parselan_error:
return -1;
}
/* fill uuidvalue_wan and uuidvalue_wcd based on uuidvalue_igd */
void complete_uuidvalues(void)
{
size_t len;
len = strlen(uuidvalue_igd);
memcpy(uuidvalue_wan, uuidvalue_igd, len+1);
switch(uuidvalue_wan[len-1]) {
case '9':
uuidvalue_wan[len-1] = 'a';
break;
case 'f':
uuidvalue_wan[len-1] = '0';
break;
default:
uuidvalue_wan[len-1]++;
}
memcpy(uuidvalue_wcd, uuidvalue_wan, len+1);
switch(uuidvalue_wcd[len-1]) {
case '9':
uuidvalue_wcd[len-1] = 'a';
break;
case 'f':
uuidvalue_wcd[len-1] = '0';
break;
default:
uuidvalue_wcd[len-1]++;
}
}
/* init phase :
* 1) read configuration file
* 2) read command line arguments
@ -739,10 +778,32 @@ init(int argc, char * * argv, struct runtime_vars * v)
case UPNPPRESENTATIONURL:
presurl = ary_options[i].value;
break;
#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
case UPNPFRIENDLY_NAME:
strncpy(friendly_name, ary_options[i].value, FRIENDLY_NAME_MAX_LEN);
friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
break;
case UPNPMANUFACTURER_NAME:
strncpy(manufacturer_name, ary_options[i].value, MANUFACTURER_NAME_MAX_LEN);
manufacturer_name[MANUFACTURER_NAME_MAX_LEN-1] = '\0';
break;
case UPNPMANUFACTURER_URL:
strncpy(manufacturer_url, ary_options[i].value, MANUFACTURER_URL_MAX_LEN);
manufacturer_url[MANUFACTURER_URL_MAX_LEN-1] = '\0';
break;
case UPNPMODEL_NAME:
strncpy(model_name, ary_options[i].value, MODEL_NAME_MAX_LEN);
model_name[MODEL_NAME_MAX_LEN-1] = '\0';
break;
case UPNPMODEL_DESCRIPTION:
strncpy(model_description, ary_options[i].value, MODEL_DESCRIPTION_MAX_LEN);
model_description[MODEL_DESCRIPTION_MAX_LEN-1] = '\0';
break;
case UPNPMODEL_URL:
strncpy(model_url, ary_options[i].value, MODEL_URL_MAX_LEN);
model_url[MODEL_URL_MAX_LEN-1] = '\0';
break;
#endif
#ifdef USE_NETFILTER
case UPNPFORWARDCHAIN:
miniupnpd_forward_chain = ary_options[i].value;
@ -765,8 +826,9 @@ init(int argc, char * * argv, struct runtime_vars * v)
break;
#endif
case UPNPUUID:
strncpy(uuidvalue+5, ary_options[i].value,
strlen(uuidvalue+5) + 1);
strncpy(uuidvalue_igd+5, ary_options[i].value,
strlen(uuidvalue_igd+5) + 1);
complete_uuidvalues();
break;
case UPNPSERIAL:
strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
@ -803,6 +865,20 @@ init(int argc, char * * argv, struct runtime_vars * v)
/*enablenatpmp = atoi(ary_options[i].value);*/
break;
#endif
#ifdef ENABLE_PCP
case UPNPPCPMINLIFETIME:
min_lifetime = atoi(ary_options[i].value);
if (min_lifetime > 120 ) {
min_lifetime = 120;
}
break;
case UPNPPCPMAXLIFETIME:
max_lifetime = atoi(ary_options[i].value);
if (max_lifetime > 86400 ) {
max_lifetime = 86400;
}
break;
#endif
#ifdef PF_ENABLE_FILTER_RULES
case UPNPQUICKRULES:
if(strcmp(ary_options[i].value, "no") == 0)
@ -830,6 +906,12 @@ init(int argc, char * * argv, struct runtime_vars * v)
optionsfile);
}
}
/* if lifetimes ae inverse*/
if (min_lifetime >= max_lifetime) {
fprintf(stderr, "Minimum lifetime (%lu) is greater than or equal to maximum lifetime (%lu).\n", min_lifetime, max_lifetime);
fprintf(stderr, "Check your configuration file.\n");
return 1;
}
}
#endif /* DISABLE_CONFIG_FILE */
@ -861,11 +943,13 @@ init(int argc, char * * argv, struct runtime_vars * v)
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
break;
case 'u':
if(i+1 < argc)
strncpy(uuidvalue+5, argv[++i], strlen(uuidvalue+5) + 1);
else
if(i+1 < argc) {
strncpy(uuidvalue_igd+5, argv[++i], strlen(uuidvalue_igd+5) + 1);
complete_uuidvalues();
} else
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
break;
#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
case 'z':
if(i+1 < argc)
strncpy(friendly_name, argv[++i], FRIENDLY_NAME_MAX_LEN);
@ -873,6 +957,7 @@ init(int argc, char * * argv, struct runtime_vars * v)
fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0';
break;
#endif
case 's':
if(i+1 < argc)
strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
@ -1200,7 +1285,10 @@ print_usage:
"\n"
/*"[-l logfile] " not functionnal */
"\t\t[-u uuid] [-s serial] [-m model_number] \n"
"\t\t[-t notify_interval] [-P pid_filename] [-z fiendly_name]\n"
"\t\t[-t notify_interval] [-P pid_filename] "
#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
"[-z fiendly_name]\n"
#endif
"\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n"
#ifdef USE_PF
"\t\t[-q queue] [-T tag]\n"
@ -1326,7 +1414,11 @@ main(int argc, char * * argv)
syslog(LOG_INFO, "Starting%s%swith external interface %s",
#ifdef ENABLE_NATPMP
#ifdef ENABLE_PCP
GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP/PCP " : " ",
#else
GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ",
#endif
#else
" ",
#endif
@ -1407,12 +1499,21 @@ main(int argc, char * * argv)
if(GETFLAG(ENABLENATPMPMASK))
{
if(OpenAndConfNATPMPSockets(snatpmp) < 0)
#ifdef ENABLE_PCP
{
syslog(LOG_ERR, "Failed to open sockets for NAT-PMP/PCP.");
} else {
syslog(LOG_NOTICE, "Listening for NAT-PMP/PCP traffic on port %u",
NATPMP_PORT);
}
#else
{
syslog(LOG_ERR, "Failed to open sockets for NAT PMP.");
} else {
syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
NATPMP_PORT);
}
#endif
#if 0
ScanNATPMPforExpiration();
#endif
@ -1727,7 +1828,26 @@ main(int argc, char * * argv)
{
if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset))
{
ProcessIncomingNATPMPPacket(snatpmp[i]);
unsigned char msg_buff[PCP_MAX_LEN];
struct sockaddr_in senderaddr;
int len;
memset(msg_buff, 0, PCP_MAX_LEN);
len = ReceiveNATPMPOrPCPPacket(snatpmp[i], &senderaddr,
msg_buff, sizeof(msg_buff));
if (len < 1)
continue;
#ifdef ENABLE_PCP
if (msg_buff[0]==0) { // version equals to 0 -> means NAT-PMP
ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len,
&senderaddr);
} else { // everything else can be PCP
ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len,
&senderaddr);
}
#else
ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len, &senderaddr);
#endif
}
}
#endif

View File

@ -31,6 +31,11 @@ enable_natpmp=yes
# enable UPNP support (default is yes)
enable_upnp=yes
# configure minimal and maximal lifetime of the port mapping in seconds
# 120s and 86400s (24h) are suggested values from PCP-base
min_lifetime=120
max_lifetime=86400
# chain names for netfilter (not used for pf or ipf).
# default is MINIUPNPD for both
#upnp_forward_chain=forwardUPnP
@ -39,9 +44,27 @@ enable_upnp=yes
# lease file location
#lease_file=/var/log/upnp.leases
# name of this service, default is "`uname -s` Router"
# to enable the next few runtime options, see compile time
# ENABLE_MANUFACTURER_INFO_CONFIGURATION (config.h)
# name of this service, default is "`uname -s` router"
#friendly_name=MiniUPnPd router
# manufacturer name, default is "`uname -s`"
#manufacturer_name=Manufacturer corp
# manufacturer url, default is URL of OS verndor
#manufacturer_url=http://miniupnp.free.fr/
# model name, default is "`uname -s` router"
#model_name=Router Model
# model description, default is "`uname -s` router"
#model_description=Very Secure Router - Model
# model url, default is URL of OS vendor
#model_url=http://miniupnp.free.fr/
# bitrates reported by daemon in bits per second
bitrate_up=1000000
bitrate_down=10000000

View File

@ -1,6 +1,6 @@
/* $Id: natpmp.c,v 1.32 2012/05/27 22:36:03 nanard Exp $ */
/* $Id: natpmp.c,v 1.33 2013/03/23 10:46:55 nanard Exp $ */
/* MiniUPnP project
* (c) 2007-2012 Thomas Bernard
* (c) 2007-2013 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 */
@ -98,7 +98,7 @@ static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr
if(!ext_if_name || ext_if_name[0]=='\0') {
resp[3] = 3; /* Network Failure (e.g. NAT box itself
* has not obtained a DHCP lease) */
} else if(getifaddr(ext_if_name, tmp, INET_ADDRSTRLEN) < 0) {
} else if(getifaddr(ext_if_name, tmp, INET_ADDRSTRLEN, NULL, NULL) < 0) {
syslog(LOG_ERR, "Failed to get IP for interface %s", ext_if_name);
resp[3] = 3; /* Network Failure (e.g. NAT box itself
* has not obtained a DHCP lease) */
@ -120,20 +120,21 @@ static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr
#endif
}
/** read the request from the socket, process it and then send the
* response back.
/*
* Receives NATPMP and PCP packets and stores them in msg_buff.
* The sender information is stored in senderaddr.
* Returns number of bytes recevied, even if number is negative.
*/
void ProcessIncomingNATPMPPacket(int s)
int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr_in* senderaddr,
unsigned char *msg_buff, size_t msg_buff_size)
{
unsigned char req[32]; /* request udp packet */
unsigned char resp[32]; /* response udp packet */
int resplen;
struct sockaddr_in senderaddr;
socklen_t senderaddrlen = sizeof(senderaddr);
socklen_t senderaddrlen = sizeof(*senderaddr);
int n;
char senderaddrstr[16];
n = recvfrom(s, req, sizeof(req), 0,
(struct sockaddr *)&senderaddr, &senderaddrlen);
n = recvfrom(s, msg_buff, msg_buff_size, 0,
(struct sockaddr *)senderaddr, &senderaddrlen);
if(n<0) {
/* EAGAIN, EWOULDBLOCK and EINTR : silently ignore (retry next time)
* other errors : log to LOG_ERR */
@ -142,14 +143,34 @@ void ProcessIncomingNATPMPPacket(int s)
errno != EINTR) {
syslog(LOG_ERR, "recvfrom(natpmp): %m");
}
return;
return n;
}
if(!inet_ntop(AF_INET, &senderaddr.sin_addr,
senderaddrstr, sizeof(senderaddrstr))) {
return n;
}
/** read the request from the socket, process it and then send the
* response back.
*/
void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
struct sockaddr_in *senderaddr)
{
unsigned char *req=msg_buff; /* request udp packet */
unsigned char resp[32]; /* response udp packet */
int resplen;
//struct sockaddr_in senderaddr;
//socklen_t senderaddrlen = sizeof(senderaddr);
int n = len;
char senderaddrstr[16];
if(!inet_ntop(AF_INET, &senderaddr->sin_addr,
senderaddrstr, sizeof(senderaddrstr))) {
syslog(LOG_ERR, "inet_ntop(natpmp): %m");
}
syslog(LOG_INFO, "NAT-PMP request received from %s:%hu %dbytes",
senderaddrstr, ntohs(senderaddr.sin_port), n);
senderaddrstr, ntohs(senderaddr->sin_port), n);
if(n<2 || ((((req[1]-1)&~1)==0) && n<12)) {
syslog(LOG_WARNING, "discarding NAT-PMP request (too short) %dBytes",
n);
@ -174,7 +195,7 @@ void ProcessIncomingNATPMPPacket(int s)
} else switch(req[1]) {
case 0: /* Public address request */
syslog(LOG_INFO, "NAT-PMP public address request");
FillPublicAddressResponse(resp, senderaddr.sin_addr.s_addr);
FillPublicAddressResponse(resp, senderaddr->sin_addr.s_addr);
resplen = 12;
break;
case 1: /* UDP port mapping request */
@ -246,7 +267,7 @@ void ProcessIncomingNATPMPPacket(int s)
}
eport = 0; /* to indicate correct removing of port mapping */
} else if(iport==0
|| !check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr.sin_addr, iport)) {
|| !check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) {
resp[3] = 2; /* Not Authorized/Refused */
} else do {
r = get_redirect_rule(ext_if_name, eport, proto,
@ -314,7 +335,7 @@ void ProcessIncomingNATPMPPacket(int s)
resp[3] = 5; /* Unsupported OPCODE */
}
n = sendto(s, resp, resplen, 0,
(struct sockaddr *)&senderaddr, sizeof(senderaddr));
(struct sockaddr *)senderaddr, sizeof(*senderaddr));
if(n<0) {
syslog(LOG_ERR, "sendto(natpmp): %m");
} else if(n<resplen) {

View File

@ -20,7 +20,11 @@
int OpenAndConfNATPMPSockets(int * sockets);
void ProcessIncomingNATPMPPacket(int s);
int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr_in* senderaddr,
unsigned char *msg_buff, size_t msg_buff_size);
void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
struct sockaddr_in *senderaddr);
#if 0
int ScanNATPMPforExpiration(void);

View File

@ -1,5 +1,5 @@
# $Id: Makefile,v 1.6 2012/04/26 13:50:48 nanard Exp $
CFLAGS?=-Wall -g -D_GNU_SOURCE -DDEBUG -Wstrict-prototypes -Wdeclaration-after-statement -ansi
CFLAGS?=-Wall -g -D_GNU_SOURCE -DDEBUG -Wstrict-prototypes -Wdeclaration-after-statement
CC = gcc
#LIBS = -liptc
@ -38,15 +38,32 @@ endif
endif
endif
all: iptcrdr.o testiptcrdr iptpinhole.o testiptpinhole
LIBS += /lib/libip4tc.so /lib/libip6tc.so
all: iptcrdr.o testiptcrdr iptpinhole.o \
testiptcrdr_peer testiptcrdr_dscp test_nfct_get
# testiptpinhole
clean:
$(RM) *.o testiptcrdr testiptpinhole
$(RM) *.o testiptcrdr testiptpinhole testiptcrdr_peer test_nfct_get \
testiptcrdr_dscp
testiptcrdr: testiptcrdr.o iptcrdr.o upnpglobalvars.o $(LIBS)
testiptcrdr: testiptcrdr.o upnpglobalvars.o $(LIBS)
testiptcrdr_peer: testiptcrdr_peer.o upnpglobalvars.o $(LIBS)
testiptcrdr_dscp: testiptcrdr_dscp.o upnpglobalvars.o $(LIBS)
testiptpinhole: testiptpinhole.o iptpinhole.o upnpglobalvars.o $(LIBS)
test_nfct_get: test_nfct_get.o test_nfct_get.o -lmnl -lnetfilter_conntrack
test_nfct_get.o: test_nfct_get.c
testiptcrdr_peer.o: testiptcrdr_peer.c
testiptcrdr_dscp.o: testiptcrdr_dscp.c
iptcrdr.o: iptcrdr.c iptcrdr.h
iptpinhole.o: iptpinhole.c iptpinhole.h

View File

@ -5,6 +5,9 @@ IPTABLES=/sbin/iptables
#display all chains relative to miniupnpd
$IPTABLES -v -n -t nat -L PREROUTING
$IPTABLES -v -n -t nat -L MINIUPNPD
$IPTABLES -v -n -t nat -L POSTROUTING
$IPTABLES -v -n -t nat -L MINIUPNPD-PCP-PEER
$IPTABLES -v -n -t mangle -L MINIUPNPD
$IPTABLES -v -n -t filter -L FORWARD
$IPTABLES -v -n -t filter -L MINIUPNPD

View File

@ -4,5 +4,7 @@ IPTABLES=/sbin/iptables
#flush all rules owned by miniupnpd
$IPTABLES -t nat -F MINIUPNPD
$IPTABLES -t nat -F MINIUPNPD-PCP-PEER
$IPTABLES -t filter -F MINIUPNPD
$IPTABLES -t mangle -F MINIUPNPD

View File

@ -13,8 +13,15 @@ $IPTABLES -t nat -N MINIUPNPD
#$IPTABLES -t nat -A PREROUTING -d $EXTIP -i $EXTIF -j MINIUPNPD
$IPTABLES -t nat -A PREROUTING -i $EXTIF -j MINIUPNPD
#adding the MINIUPNPD chain for mangle
$IPTABLES -t mangle -N MINIUPNPD
$IPTABLES -t mangle -A PREROUTING -i $EXTIF -j MINIUPNPD
#adding the MINIUPNPD chain for filter
$IPTABLES -t filter -N MINIUPNPD
#adding the rule to MINIUPNPD
$IPTABLES -t filter -A FORWARD -i $EXTIF ! -o $EXTIF -j MINIUPNPD
#adding the MINIUPNPD chain for nat
$IPTABLES -t nat -N MINIUPNPD-PCP-PEER
$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MINIUPNPD-PCP-PEER

View File

@ -13,9 +13,19 @@ $IPTABLES -t nat -F MINIUPNPD
$IPTABLES -t nat -D PREROUTING -i $EXTIF -j MINIUPNPD
$IPTABLES -t nat -X MINIUPNPD
#removing the MINIUPNPD chain for mangle
$IPTABLES -t mangle -F MINIUPNPD
$IPTABLES -t mangle -D PREROUTING -i $EXTIF -j MINIUPNPD
$IPTABLES -t mangle -X MINIUPNPD
#removing the MINIUPNPD chain for filter
$IPTABLES -t filter -F MINIUPNPD
#adding the rule to MINIUPNPD
$IPTABLES -t filter -D FORWARD -i $EXTIF ! -o $EXTIF -j MINIUPNPD
$IPTABLES -t filter -X MINIUPNPD
#removing the MINIUPNPD-PCP-PEER chain for nat
$IPTABLES -t nat -F MINIUPNPD-PCP-PEER
#removing the rule to MINIUPNPD-PCP-PEER
$IPTABLES -t nat -D POSTROUTING -o $EXTIF -j MINIUPNPD-PCP-PEER
$IPTABLES -t nat -X MINIUPNPD-PCP-PEER

View File

@ -14,6 +14,7 @@
#include <arpa/inet.h>
#include <dlfcn.h>
#include <xtables.h>
#include <linux/netfilter/xt_DSCP.h>
#include <libiptc/libiptc.h>
#include <linux/version.h>
@ -71,6 +72,17 @@ static int
add_filter_rule(int proto, const char * rhost,
const char * iaddr, unsigned short iport);
static int
addpeernatrule(int proto,
const char * eaddr, unsigned short eport,
const char * iaddr, unsigned short iport,
const char * rhost, unsigned short rport);
static int
addpeerdscprule(int proto, unsigned char dscp,
const char * iaddr, unsigned short iport,
const char * rhost, unsigned short rport);
/* dummy init and shutdown functions */
int init_redirect(void)
{
@ -215,6 +227,41 @@ add_redirect_rule2(const char * ifname,
return r;
}
/* add_redirect_rule2() */
int
add_peer_redirect_rule2(const char * ifname,
const char * rhost, unsigned short rport,
const char * eaddr, unsigned short eport,
const char * iaddr, unsigned short iport, int proto,
const char * desc, unsigned int timestamp)
{
int r;
UNUSED(ifname);
r = addpeernatrule(proto, eaddr, eport, iaddr, iport, rhost, rport);
if(r >= 0)
add_redirect_desc(eport, proto, desc, timestamp);
return r;
}
int
add_peer_dscp_rule2(const char * ifname,
const char * rhost, unsigned short rport,
unsigned char dscp,
const char * iaddr, unsigned short iport, int proto,
const char * desc, unsigned int timestamp)
{
int r;
UNUSED(ifname);
UNUSED(desc);
UNUSED(timestamp);
r = addpeerdscprule(proto, dscp, iaddr, iport, rhost, rport);
/* if(r >= 0)
add_redirect_desc(dscp, proto, desc, timestamp); */
return r;
}
int
add_filter_rule2(const char * ifname,
const char * rhost, const char * iaddr,
@ -429,6 +476,120 @@ get_redirect_rule_by_index(int index,
return r;
}
/* get_peer_rule_by_index()
* return -1 when the rule was not found */
int
get_peer_rule_by_index(int index,
char * ifname, unsigned short * eport,
char * iaddr, int iaddrlen, unsigned short * iport,
int * proto, char * desc, int desclen,
char * rhost, int rhostlen, unsigned short * rport,
unsigned int * timestamp,
u_int64_t * packets, u_int64_t * bytes)
{
int r = -1;
#if USE_INDEX_FROM_DESC_LIST && 0
r = get_redirect_desc_by_index(index, eport, proto,
desc, desclen, timestamp);
if (r==0)
{
r = get_redirect_rule(ifname, *eport, *proto, iaddr, iaddrlen, iport,
0, 0, packets, bytes);
}
#else
int i = 0;
IPTC_HANDLE h;
const struct ipt_entry * e;
const struct ipt_entry_target * target;
const struct ip_nat_multi_range * mr;
const struct ipt_entry_match *match;
UNUSED(ifname);
h = iptc_init("nat");
if(!h)
{
syslog(LOG_ERR, "get_peer_rule_by_index() : "
"iptc_init() failed : %s",
iptc_strerror(errno));
return -1;
}
if(!iptc_is_chain(miniupnpd_peer_chain, h))
{
syslog(LOG_ERR, "chain %s not found", miniupnpd_peer_chain);
}
else
{
#ifdef IPTABLES_143
for(e = iptc_first_rule(miniupnpd_peer_chain, h);
e;
e = iptc_next_rule(e, h))
#else
for(e = iptc_first_rule(miniupnpd_peer_chain, &h);
e;
e = iptc_next_rule(e, &h))
#endif
{
if(i==index)
{
*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 (rport)
*rport = info->dpts[0];
if (iport)
*iport = info->spts[0];
}
else
{
const struct ipt_udp * info;
info = (const struct ipt_udp *)match->data;
if (rport)
*rport = info->dpts[0];
if (iport)
*iport = info->spts[0];
}
target = (void *)e + e->target_offset;
mr = (const struct ip_nat_multi_range *)&target->data[0];
*eport = ntohs(mr->range[0].min.all);
get_redirect_desc(*eport, *proto, desc, desclen, timestamp);
if(packets)
*packets = e->counters.pcnt;
if(bytes)
*bytes = e->counters.bcnt;
/* rhost */
if(rhost && rhostlen > 0) {
if(e->ip.dst.s_addr) {
snprintip(rhost, rhostlen, ntohl(e->ip.dst.s_addr));
} else {
rhost[0] = '\0';
}
}
if(iaddr && iaddrlen > 0) {
if(e->ip.src.s_addr) {
snprintip(iaddr, iaddrlen, ntohl(e->ip.src.s_addr));
} else {
rhost[0] = '\0';
}
}
r = 0;
break;
}
i++;
}
}
if(h)
#ifdef IPTABLES_143
iptc_free(h);
#else
iptc_free(&h);
#endif
#endif
return r;
}
/* delete_rule_and_commit() :
* subfunction used in delete_redirect_and_filter_rules() */
static int
@ -471,7 +632,7 @@ delete_rule_and_commit(unsigned int index, IPTC_HANDLE h,
int
delete_redirect_and_filter_rules(unsigned short eport, int proto)
{
int r = -1;
int r = -1, r2 = -1;
unsigned index = 0;
unsigned i = 0;
IPTC_HANDLE h;
@ -588,22 +749,134 @@ delete_redirect_and_filter_rules(unsigned short eport, int proto)
if(iaddr != e->ip.dst.s_addr)
continue;
index = i;
syslog(LOG_INFO, "Trying to delete filter rule at index %u", index);
r = delete_rule_and_commit(index, h, miniupnpd_forward_chain, "delete_filter_rule");
h = NULL;
break;
}
}
syslog(LOG_INFO, "Trying to delete filter rule at index %u", index);
r = delete_rule_and_commit(index, h, miniupnpd_forward_chain, "delete_filter_rule");
}
if(h)
#ifdef IPTABLES_143
iptc_free(h);
#else
iptc_free(&h);
#endif
}
/*delete PEER rule*/
if((h = iptc_init("nat")))
{
i = 0;
/* we must find the right index for the filter rule */
#ifdef IPTABLES_143
for(e = iptc_first_rule(miniupnpd_peer_chain, h);
e;
e = iptc_next_rule(e, h), i++)
#else
for(e = iptc_first_rule(miniupnpd_peer_chain, &h);
e;
e = iptc_next_rule(e, &h), i++)
#endif
{
if(proto==e->ip.proto)
{
target = (void *)e + e->target_offset;
mr = (const struct ip_nat_multi_range *)&target->data[0];
if (eport != ntohs(mr->range[0].min.all)) {
continue;
}
iaddr = e->ip.src.s_addr;
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;
iport = info->spts[0];
}
else
{
const struct ipt_udp * info;
info = (const struct ipt_udp *)match->data;
iport = info->dpts[0];
}
index = i;
syslog(LOG_INFO, "Trying to delete peer rule at index %u", index);
r2 = delete_rule_and_commit(index, h, miniupnpd_peer_chain, "delete_peer_rule");
h = NULL;
break;
}
}
}
if(h)
#ifdef IPTABLES_143
iptc_free(h);
#else
iptc_free(&h);
#endif
/*delete DSCP rule*/
if((r2==0)&&(h = iptc_init("mangle")))
{
i = 0;
index = -1;
/* we must find the right index for the filter rule */
#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;
/*syslog(LOG_DEBUG, "filter rule #%u: %s %s",
i, match->u.user.name, inet_ntoa(e->ip.dst));*/
if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN))
{
const struct ipt_tcp * info;
info = (const struct ipt_tcp *)match->data;
if(iport != info->spts[0])
continue;
}
else
{
const struct ipt_udp * info;
info = (const struct ipt_udp *)match->data;
if(iport != info->spts[0])
continue;
}
if(iaddr != e->ip.src.s_addr)
continue;
index = i;
syslog(LOG_INFO, "Trying to delete dscp rule at index %u", index);
r2 = delete_rule_and_commit(index, h, miniupnpd_nat_chain, "delete_dscp_rule");
h = NULL;
break;
}
}
if (h)
#ifdef IPTABLES_143
iptc_free(h);
#else
iptc_free(&h);
#endif
}
del_redirect_desc(eport, proto);
return r;
return r*r2;
}
/* ==================================== */
/* TODO : add the -m state --state NEW,ESTABLISHED,RELATED
* only for the filter rule */
static struct ipt_entry_match *
get_tcp_match(unsigned short dport)
get_tcp_match(unsigned short dport, unsigned short sport)
{
struct ipt_entry_match *match;
struct ipt_tcp * tcpinfo;
@ -614,15 +887,25 @@ get_tcp_match(unsigned short dport)
match->u.match_size = size;
strncpy(match->u.user.name, "tcp", sizeof(match->u.user.name));
tcpinfo = (struct ipt_tcp *)match->data;
tcpinfo->spts[0] = 0; /* all source ports */
tcpinfo->spts[1] = 0xFFFF;
tcpinfo->dpts[0] = dport; /* specified destination port */
tcpinfo->dpts[1] = dport;
if (sport == 0) {
tcpinfo->spts[0] = 0; /* all source ports */
tcpinfo->spts[1] = 0xFFFF;
} else {
tcpinfo->spts[0] = sport; /* specified source port */
tcpinfo->spts[1] = sport;
}
if (dport == 0) {
tcpinfo->dpts[0] = 0; /* all destination ports */
tcpinfo->dpts[1] = 0xFFFF;
} else {
tcpinfo->dpts[0] = dport; /* specified destination port */
tcpinfo->dpts[1] = dport;
}
return match;
}
static struct ipt_entry_match *
get_udp_match(unsigned short dport)
get_udp_match(unsigned short dport, unsigned short sport)
{
struct ipt_entry_match *match;
struct ipt_udp * udpinfo;
@ -633,10 +916,20 @@ get_udp_match(unsigned short dport)
match->u.match_size = size;
strncpy(match->u.user.name, "udp", sizeof(match->u.user.name));
udpinfo = (struct ipt_udp *)match->data;
udpinfo->spts[0] = 0; /* all source ports */
udpinfo->spts[1] = 0xFFFF;
udpinfo->dpts[0] = dport; /* specified destination port */
udpinfo->dpts[1] = dport;
if (sport == 0) {
udpinfo->spts[0] = 0; /* all source ports */
udpinfo->spts[1] = 0xFFFF;
} else {
udpinfo->spts[0] = sport; /* specified source port */
udpinfo->spts[1] = sport;
}
if (dport == 0) {
udpinfo->dpts[0] = 0; /* all destination ports */
udpinfo->dpts[1] = 0xFFFF;
} else {
udpinfo->dpts[0] = dport; /* specified destination port */
udpinfo->dpts[1] = dport;
}
return match;
}
@ -664,6 +957,48 @@ get_dnat_target(const char * daddr, unsigned short dport)
return target;
}
static struct ipt_entry_target *
get_snat_target(const char * saddr, unsigned short sport)
{
struct ipt_entry_target * target;
struct ip_nat_multi_range * mr;
struct ip_nat_range * range;
size_t size;
size = IPT_ALIGN(sizeof(struct ipt_entry_target))
+ IPT_ALIGN(sizeof(struct ip_nat_multi_range));
target = calloc(1, size);
target->u.target_size = size;
strncpy(target->u.user.name, "SNAT", sizeof(target->u.user.name));
/* one ip_nat_range already included in ip_nat_multi_range */
mr = (struct ip_nat_multi_range *)&target->data[0];
mr->rangesize = 1;
range = &mr->range[0];
range->min_ip = range->max_ip = inet_addr(saddr);
range->flags |= IP_NAT_RANGE_MAP_IPS;
range->min.all = range->max.all = htons(sport);
range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
return target;
}
static struct ipt_entry_target *
get_dscp_target(unsigned char dscp)
{
struct ipt_entry_target * target;
struct xt_DSCP_info * di;
size_t size;
size = IPT_ALIGN(sizeof(struct ipt_entry_target))
+ IPT_ALIGN(sizeof(struct xt_DSCP_info));
target = calloc(1, size);
target->u.target_size = size;
strncpy(target->u.user.name, "DSCP", sizeof(target->u.user.name));
/* one ip_nat_range already included in ip_nat_multi_range */
di = (struct xt_DSCP_info *)&target->data[0];
di->dscp=dscp;
return target;
}
/* iptc_init_verify_and_append()
* return 0 on success, -1 on failure */
static int
@ -751,11 +1086,11 @@ addnatrule(int proto, unsigned short eport,
e->ip.proto = proto;
if(proto == IPPROTO_TCP)
{
match = get_tcp_match(eport);
match = get_tcp_match(eport, 0);
}
else
{
match = get_udp_match(eport);
match = get_udp_match(eport, 0);
}
e->nfcache = NFC_IP_DST_PT;
target = get_dnat_target(iaddr, iport);
@ -783,6 +1118,126 @@ addnatrule(int proto, unsigned short eport,
free(e);
return r;
}
/* iptables -t nat -A MINIUPNPD-PCP-PEER -s iaddr -d rhost
* -p proto --sport iport --dport rport -j SNAT
* --to-source ext_ip:eport */
static int
addpeernatrule(int proto,
const char * eaddr, unsigned short eport,
const char * iaddr, unsigned short iport,
const char * rhost, unsigned short rport)
{
int r = 0;
struct ipt_entry * e;
struct ipt_entry_match *match = NULL;
struct ipt_entry_target *target = NULL;
e = calloc(1, sizeof(struct ipt_entry));
e->ip.proto = proto;
/* TODO: Fill port matches and SNAT */
if(proto == IPPROTO_TCP)
{
match = get_tcp_match(rport, iport);
}
else
{
match = get_udp_match(rport, iport);
}
e->nfcache = NFC_IP_DST_PT | NFC_IP_SRC_PT;
target = get_snat_target(eaddr, eport);
e->nfcache |= NFC_UNKNOWN;
e = realloc(e, sizeof(struct ipt_entry)
+ match->u.match_size
+ target->u.target_size);
memcpy(e->elems, match, match->u.match_size);
memcpy(e->elems + match->u.match_size, target, target->u.target_size);
e->target_offset = sizeof(struct ipt_entry)
+ match->u.match_size;
e->next_offset = sizeof(struct ipt_entry)
+ match->u.match_size
+ target->u.target_size;
/* internal host */
if(iaddr && (iaddr[0] != '\0') && (0 != strcmp(iaddr, "*")))
{
e->ip.src.s_addr = inet_addr(iaddr);
e->ip.smsk.s_addr = INADDR_NONE;
}
/* remote host */
if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*")))
{
e->ip.dst.s_addr = inet_addr(rhost);
e->ip.dmsk.s_addr = INADDR_NONE;
}
r = iptc_init_verify_and_append("nat", miniupnpd_peer_chain, e, "addpeernatrule()");
free(target);
free(match);
free(e);
return r;
}
/* iptables -t mangle -A MINIUPNPD -s iaddr -d rhost
* -p proto --sport iport --dport rport -j DSCP
* --set-dscp 0xXXXX */
static int
addpeerdscprule(int proto, unsigned char dscp,
const char * iaddr, unsigned short iport,
const char * rhost, unsigned short rport)
{
int r = 0;
struct ipt_entry * e;
struct ipt_entry_match *match = NULL;
struct ipt_entry_target *target = NULL;
e = calloc(1, sizeof(struct ipt_entry));
e->ip.proto = proto;
/* TODO: Fill port matches and SNAT */
if(proto == IPPROTO_TCP)
{
match = get_tcp_match(rport, iport);
}
else
{
match = get_udp_match(rport, iport);
}
e->nfcache = NFC_IP_DST_PT | NFC_IP_SRC_PT;
target = get_dscp_target(dscp);
e->nfcache |= NFC_UNKNOWN;
e = realloc(e, sizeof(struct ipt_entry)
+ match->u.match_size
+ target->u.target_size);
memcpy(e->elems, match, match->u.match_size);
memcpy(e->elems + match->u.match_size, target, target->u.target_size);
e->target_offset = sizeof(struct ipt_entry)
+ match->u.match_size;
e->next_offset = sizeof(struct ipt_entry)
+ match->u.match_size
+ target->u.target_size;
/* internal host */
if(iaddr && (iaddr[0] != '\0') && (0 != strcmp(iaddr, "*")))
{
e->ip.src.s_addr = inet_addr(iaddr);
e->ip.smsk.s_addr = INADDR_NONE;
}
/* remote host */
if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*")))
{
e->ip.dst.s_addr = inet_addr(rhost);
e->ip.dmsk.s_addr = INADDR_NONE;
}
r = iptc_init_verify_and_append("mangle", miniupnpd_nat_chain, e,
"addpeerDSCPrule()");
free(target);
free(match);
free(e);
return r;
}
/* ================================= */
static struct ipt_entry_target *
get_accept_target(void)
@ -812,11 +1267,11 @@ add_filter_rule(int proto, const char * rhost,
e->ip.proto = proto;
if(proto == IPPROTO_TCP)
{
match = get_tcp_match(iport);
match = get_tcp_match(iport,0);
}
else
{
match = get_udp_match(iport);
match = get_udp_match(iport,0);
}
e->nfcache = NFC_IP_DST_PT;
e->ip.dst.s_addr = inet_addr(iaddr);

View File

@ -16,6 +16,13 @@ add_redirect_rule2(const char * ifname,
const char * iaddr, unsigned short iport, int proto,
const char * desc, unsigned int timestamp);
int
add_peer_redirect_rule2(const char * ifname,
const char * rhost, unsigned short rport,
const char * eaddr, unsigned short eport,
const char * iaddr, unsigned short iport, int proto,
const char * desc, unsigned int timestamp);
int
add_filter_rule2(const char * ifname,
const char * rhost, const char * iaddr,
@ -25,6 +32,23 @@ add_filter_rule2(const char * ifname,
int
delete_redirect_and_filter_rules(unsigned short eport, int proto);
int
add_peer_dscp_rule2(const char * ifname,
const char * rhost, unsigned short rport,
unsigned char dscp,
const char * iaddr, unsigned short iport, int proto,
const char * desc, unsigned int timestamp);
int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto,
struct sockaddr* ret_ext);
int
get_peer_rule_by_index(int index,
char * ifname, unsigned short * eport,
char * iaddr, int iaddrlen, unsigned short * iport,
int * proto, char * desc, int desclen,
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,

View File

@ -0,0 +1,258 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <arpa/inet.h>
#ifdef USE_NFCT
#include <libmnl/libmnl.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include <linux/netfilter/nf_conntrack_tcp.h>
struct data_cb_s
{
struct sockaddr_storage * ext;
uint8_t found;
};
static int data_cb(const struct nlmsghdr *nlh, void *data)
{
struct nf_conntrack *ct;
struct data_cb_s * d = (struct data_cb_s*) data;
struct sockaddr_in* ext4 = (struct sockaddr_in*) d->ext;
ct = nfct_new();
if (ct == NULL)
return MNL_CB_OK;
nfct_nlmsg_parse(nlh, ct);
if (data) {
ext4->sin_addr.s_addr = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST);
ext4->sin_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST);
}
d->found = 1;
nfct_destroy(ct);
return MNL_CB_OK;
}
int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto,
struct sockaddr_storage* ret_ext)
{
struct mnl_socket *nl;
struct nlmsghdr *nlh;
struct nfgenmsg *nfh;
char buf[MNL_SOCKET_BUFFER_SIZE];
unsigned int seq, portid;
struct nf_conntrack *ct;
int ret;
struct data_cb_s data;
if ((!src)&&(!dst)) {
return 0;
}
if (src->sa_family != dst->sa_family) {
return 0;
}
nl = mnl_socket_open(NETLINK_NETFILTER);
if (nl == NULL) {
// perror("mnl_socket_open");
goto free_nl;
}
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
// perror("mnl_socket_bind");
goto free_nl;
}
portid = mnl_socket_get_portid(nl);
memset(buf, 0, sizeof(buf));
nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET;
nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
nlh->nlmsg_seq = seq = time(NULL);
nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
nfh->nfgen_family = src->sa_family;
nfh->version = NFNETLINK_V0;
nfh->res_id = 0;
ct = nfct_new();
if (ct == NULL) {
goto free_nl;
}
nfct_set_attr_u8(ct, ATTR_L3PROTO, src->sa_family);
if (src->sa_family == AF_INET) {
struct sockaddr_in *src4 = (struct sockaddr_in *)src;
struct sockaddr_in *dst4 = (struct sockaddr_in *)dst;
nfct_set_attr_u32(ct, ATTR_IPV4_SRC, src4->sin_addr.s_addr);
nfct_set_attr_u32(ct, ATTR_IPV4_DST, dst4->sin_addr.s_addr);
nfct_set_attr_u16(ct, ATTR_PORT_SRC, src4->sin_port);
nfct_set_attr_u16(ct, ATTR_PORT_DST, dst4->sin_port);
} else if (src->sa_family == AF_INET6) {
struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)src;
struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst;
nfct_set_attr(ct, ATTR_IPV6_SRC, &src6->sin6_addr);
nfct_set_attr(ct, ATTR_IPV6_DST, &dst6->sin6_addr);
nfct_set_attr_u16(ct, ATTR_PORT_SRC, src6->sin6_port);
nfct_set_attr_u16(ct, ATTR_PORT_DST, dst6->sin6_port);
}
nfct_set_attr_u8(ct, ATTR_L4PROTO, proto);
nfct_nlmsg_build(nlh, ct);
ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
if (ret == -1) {
goto free_ct;
}
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
data.ext = ret_ext;
data.found = 0;
while (ret > 0) {
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, &data);
if (ret <= MNL_CB_STOP)
break;
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
}
free_ct:
nfct_destroy(ct);
free_nl:
mnl_socket_close(nl);
return data.found;
}
#else
#define DST "dst="
#define DST_PORT "dport="
#define SRC "src="
#define SRC_PORT "sport="
#define IP_CONNTRACK_LOCATION "/proc/net/ip_conntrack"
#define NF_CONNTRACK_LOCATION "/proc/net/nf_conntrack"
int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto,
struct sockaddr_storage* ret_ext)
{
FILE *f;
int af;
if (!src)
return -2;
af = src->sa_family;
if ((f = fopen(NF_CONNTRACK_LOCATION, "r")) == NULL) {
if ((f = fopen(IP_CONNTRACK_LOCATION, "r")) == NULL) {
printf("could not read info about connections from the kernel, "
"make sure netfilter is enabled in kernel or by modules.\n");
return -1;
}
}
while (!feof(f)) {
char line[256], *str;
memset(line, 0, sizeof(line));
str = fgets(line, sizeof(line), f);
if (line[0] != 0) {
char *token, *saveptr;
int j;
uint8_t src_f, src_port_f, dst_f, dst_port_f;
src_f=src_port_f=dst_f=dst_port_f=0;
for (j = 1; ; j++, str = NULL) {
token = strtok_r(str, " ", &saveptr);
if (token == NULL)
break;
if ((j==2)&&(af!=atoi(token)))
break;
if ((j==4)&&(proto!=atoi(token)))
break;
if (j<=4)
continue;
if (strncmp(token, SRC, sizeof(SRC) - 1) == 0) {
char *srcip = token + sizeof(SRC) - 1;
uint32_t buf[4];
memset(buf,0,sizeof(buf));
if (inet_pton(af, srcip, buf)!=1)
break;
if (af==AF_INET) {
struct sockaddr_in *src4=(struct sockaddr_in*)src;
if (!src_f) {
if (src4->sin_addr.s_addr != buf[0])
break;
src_f = 1;
}
}
}
if (strncmp(token, SRC_PORT, sizeof(SRC_PORT) - 1) == 0) {
char *src_port = token + sizeof(SRC_PORT) - 1;
uint16_t port=atoi(src_port);
if (af==AF_INET) {
struct sockaddr_in *src4=(struct sockaddr_in*)src;
if (!src_port_f) {
if (ntohs(src4->sin_port) != port)
break;
src_port_f = 1;
}
}
}
if (strncmp(token, DST, sizeof(DST) - 1) == 0) {
char *dstip = token + sizeof(DST) - 1;
uint32_t buf[4];
memset(buf,0,sizeof(buf));
if (inet_pton(af, dstip, buf)!=1)
break;
if (af==AF_INET) {
struct sockaddr_in *dst4=(struct sockaddr_in*)dst;
if (!dst_f) {
if (dst4->sin_addr.s_addr != buf[0])
break;
dst_f = 1;
} else {
struct sockaddr_in*ret4=(struct sockaddr_in*)ret_ext;
ret_ext->ss_family = AF_INET;
ret4->sin_addr.s_addr = buf[0];
}
}
}
if (strncmp(token, DST_PORT, sizeof(DST_PORT)-1) == 0) {
char *dst_port = token + sizeof(DST_PORT) - 1;
uint16_t port=atoi(dst_port);
if (af==AF_INET) {
struct sockaddr_in *dst4=(struct sockaddr_in*)dst;
if (!dst_port_f) {
if (ntohs(dst4->sin_port) != port)
break;
dst_port_f = 1;
} else {
struct sockaddr_in*ret4=(struct sockaddr_in*)ret_ext;
ret_ext->ss_family = AF_INET;
ret4->sin_port = htons(port);
}
}
}
}
if (src_f && src_port_f && dst_f && dst_port_f) {
fclose(f);
return 1;
}
}
}
fclose(f);
return 0;
}
#endif

View File

@ -0,0 +1,50 @@
#include "nfct_get.c"
int main(int argc, char *argv[])
{
struct sockaddr_storage src, dst, ext;
char buff[INET6_ADDRSTRLEN];
if (argc!=5)
return 0;
if (1 != inet_pton(AF_INET, argv[1],
&((struct sockaddr_in*)&src)->sin_addr)) {
if (1 != inet_pton(AF_INET6, argv[1],
&((struct sockaddr_in6*) &src)->sin6_addr)) {
perror("bad input param");
} else {
((struct sockaddr_in6*)(&src))->sin6_port = htons(atoi(argv[2]));
src.ss_family = AF_INET6;
}
} else {
((struct sockaddr_in*)(&src))->sin_port = htons(atoi(argv[2]));
src.ss_family = AF_INET;
}
if (1 != inet_pton(AF_INET, argv[3],
&((struct sockaddr_in*)&dst)->sin_addr)) {
if (1 != inet_pton(AF_INET6, argv[3],
&((struct sockaddr_in6*) &dst)->sin6_addr)) {
perror("bad input param");
} else {
((struct sockaddr_in6*)(&dst))->sin6_port = htons(atoi(argv[4]));
dst.ss_family = AF_INET6;
}
} else {
((struct sockaddr_in*)(&dst))->sin_port = htons(atoi(argv[4]));
dst.ss_family = AF_INET;
}
if (get_nat_ext_addr((struct sockaddr*)&src, (struct sockaddr*)&dst,
IPPROTO_TCP, &ext)) {
printf("Ext address %s:%d\n",
inet_ntop(src.ss_family,
&((struct sockaddr_in*)&ext)->sin_addr,
buff, sizeof(buff)),
ntohs(((struct sockaddr_in*)(&ext))->sin_port));
} else {
printf("no entry\n");
}
return 0;
}

View File

@ -10,7 +10,7 @@
#include <netinet/in.h>
#include <syslog.h>
#include "iptcrdr.h"
#include "iptcrdr.c"
#include "../commonrdr.h"
#ifndef PRIu64
@ -30,13 +30,11 @@ main(int argc, char ** argv)
eport = (unsigned short)atoi(argv[1]);
iaddr = argv[2];
iport = (unsigned short)atoi(argv[3]);
#if 0
printf("trying to redirect port %hu to %s:%hu\n", eport, iaddr, iport);
if(addnatrule(IPPROTO_TCP, eport, iaddr, iport) < 0)
if(addnatrule(IPPROTO_TCP, eport, iaddr, iport, NULL) < 0)
return -1;
if(add_filter_rule(IPPROTO_TCP, iaddr, iport) < 0)
if(add_filter_rule(IPPROTO_TCP, NULL, iaddr, iport) < 0)
return -1;
#endif
/* test */
{
unsigned short p1, p2;

View File

@ -0,0 +1,73 @@
/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <syslog.h>
#include "iptcrdr.h"
#include "../commonrdr.h"
#include "iptcrdr.c"
#ifndef PRIu64
#define PRIu64 "llu"
#endif
int
main(int argc, char ** argv)
{
unsigned char dscp;
unsigned short iport, rport;
const char * iaddr, *rhost;
printf("Usage %s <dscp> <internal_ip> <internal_port> <peer_ip> <peer_port>\n", argv[0]);
if(argc<6)
return -1;
openlog("testiptcrdr_peer", LOG_PERROR|LOG_CONS, LOG_LOCAL0);
dscp = (unsigned short)atoi(argv[1]);
iaddr = argv[2];
iport = (unsigned short)atoi(argv[3]);
rhost = argv[4];
rport = (unsigned short)atoi(argv[5]);
#if 1
if(addpeerdscprule(IPPROTO_TCP, dscp, iaddr, iport, rhost, rport) < 0)
return -1;
#endif
/* test */
{
unsigned short p1, p2;
char addr[16];
int proto2;
char desc[256];
char rhost[256];
unsigned int timestamp;
u_int64_t packets, bytes;
desc[0] = '\0';
if(get_redirect_rule_by_index(0, "", &p1,
addr, sizeof(addr), &p2,
&proto2, desc, sizeof(desc),
rhost, sizeof(rhost),
&timestamp,
&packets, &bytes) < 0)
{
printf("rule not found\n");
}
else
{
printf("redirected port %hu to %s:%hu proto %d packets=%" PRIu64 " bytes=%" PRIu64 "\n",
p1, addr, p2, proto2, packets, bytes);
}
}
printf("trying to list nat rules :\n");
list_redirect_rule(argv[1]);
printf("deleting\n");
// delete_redirect_and_filter_rules(eport, IPPROTO_TCP);
return 0;
}

View File

@ -0,0 +1,74 @@
/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <syslog.h>
#include "iptcrdr.h"
#include "../commonrdr.h"
#include "iptcrdr.c"
#ifndef PRIu64
#define PRIu64 "llu"
#endif
int
main(int argc, char ** argv)
{
unsigned short eport, iport, rport;
const char * eaddr, *iaddr, *rhost;
printf("Usage %s <ext_ip> <ext_port> <internal_ip> <internal_port> <peer_ip> <peer_port>\n", argv[0]);
if(argc<6)
return -1;
openlog("testiptcrdr_peer", LOG_PERROR|LOG_CONS, LOG_LOCAL0);
eaddr = argv[1];
eport = (unsigned short)atoi(argv[2]);
iaddr = argv[3];
iport = (unsigned short)atoi(argv[4]);
rhost = argv[5];
rport = (unsigned short)atoi(argv[6]);
#if 1
printf("trying to redirect port %hu to %s:%hu\n", eport, iaddr, iport);
if(addpeernatrule(IPPROTO_TCP, eaddr, eport, iaddr, iport, rhost, rport) < 0)
return -1;
#endif
/* test */
{
unsigned short p1, p2;
char addr[16];
int proto2;
char desc[256];
char rhost[256];
unsigned int timestamp;
u_int64_t packets, bytes;
desc[0] = '\0';
if(get_redirect_rule_by_index(0, "", &p1,
addr, sizeof(addr), &p2,
&proto2, desc, sizeof(desc),
rhost, sizeof(rhost),
&timestamp,
&packets, &bytes) < 0)
{
printf("rule not found\n");
}
else
{
printf("redirected port %hu to %s:%hu proto %d packets=%" PRIu64 " bytes=%" PRIu64 "\n",
p1, addr, p2, proto2, packets, bytes);
}
}
printf("trying to list nat rules :\n");
list_redirect_rule(argv[1]);
printf("deleting\n");
delete_redirect_and_filter_rules(eport, IPPROTO_TCP);
return 0;
}

View File

@ -2,7 +2,7 @@
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* author: Ryan Wagoner
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -14,6 +14,9 @@
#include "config.h"
#include "options.h"
#include "upnppermissions.h"
#ifdef PCP_SADSCP
#include "pcplearndscp.h"
#endif // PCP_SADSPC
#include "upnpglobalvars.h"
#ifndef DISABLE_CONFIG_FILE
@ -32,7 +35,14 @@ static const struct {
{ UPNPBITRATE_UP, "bitrate_up" },
{ UPNPBITRATE_DOWN, "bitrate_down" },
{ UPNPPRESENTATIONURL, "presentation_url" },
#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
{ UPNPFRIENDLY_NAME, "friendly_name" },
{ UPNPMANUFACTURER_NAME, "manufacturer_name" },
{ UPNPMANUFACTURER_URL, "manufacturer_url" },
{ UPNPMODEL_NAME, "model_name" },
{ UPNPMODEL_DESCRIPTION, "model_description" },
{ UPNPMODEL_URL, "model_url" },
#endif
{ UPNPNOTIFY_INTERVAL, "notify_interval" },
{ UPNPSYSTEM_UPTIME, "system_uptime" },
{ UPNPPACKET_LOG, "packet_log" },
@ -47,6 +57,10 @@ static const struct {
#endif
#ifdef ENABLE_NATPMP
{ UPNPENABLENATPMP, "enable_natpmp"},
#endif
#ifdef ENABLE_PCP
{ UPNPPCPMINLIFETIME, "min_lifetime"},
{ UPNPPCPMAXLIFETIME, "max_lifetime"},
#endif
{ UPNPENABLE, "enable_upnp"},
#ifdef USE_PF
@ -147,6 +161,33 @@ readoptionsfile(const char * fname)
}
continue;
}
#ifdef PCP_SADSCP
/* check for DSCP values configuration */
if(0 == memcmp(name, "set_learn_dscp", sizeof("set_learn_dscp")-1) )
{
tmp = realloc(dscp_values_list, sizeof(struct dscp_values) * (num_dscp_values+1));
if(tmp == NULL)
{
fprintf(stderr, "memory allocation error. DSCP line in file %s line %d\n",
fname, linenum);
}
else
{
dscp_values_list = tmp;
/* parse the rule */
if(read_learn_dscp_line(dscp_values_list + num_dscp_values, name) >= 0)
{
num_dscp_values++;
}
else
{
fprintf(stderr, "parsing error file %s line %d : %s\n",
fname, linenum, name);
}
}
continue;
}
#endif //PCP_SADSCP
if(!(equals = strchr(name, '=')))
{
fprintf(stderr, "parsing error file %s line %d : %s\n",
@ -248,6 +289,21 @@ freeoptions(void)
upnppermlist = NULL;
num_upnpperm = 0;
}
#ifdef PCP_SADSCP
if(dscp_values_list)
{
unsigned int i;
for (i = 0; i < num_dscp_values; i++) {
if (dscp_values_list[i].app_name) {
free(dscp_values_list[i].app_name);
dscp_values_list[i].app_name = NULL;
}
}
free(dscp_values_list);
dscp_values_list = NULL;
num_dscp_values = 0;
}
#endif //PCP_SADSCP
}
#endif /* DISABLE_CONFIG_FILE */

View File

@ -2,7 +2,7 @@
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* author: Ryan Wagoner
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -22,7 +22,14 @@ enum upnpconfigoptions {
UPNPBITRATE_UP, /* "bitrate_up" */
UPNPBITRATE_DOWN, /* "bitrate_down" */
UPNPPRESENTATIONURL, /* presentation_url */
#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
UPNPFRIENDLY_NAME, /* "friendly_name" */
UPNPMANUFACTURER_NAME, /* "manufacturer_name" */
UPNPMANUFACTURER_URL, /* "manufacturer_url" */
UPNPMODEL_NAME, /* "model_name" */
UPNPMODEL_DESCRIPTION, /* "model_description" */
UPNPMODEL_URL, /* "model_url" */
#endif
UPNPNOTIFY_INTERVAL, /* notify_interval */
UPNPSYSTEM_UPTIME, /* "system_uptime" */
UPNPPACKET_LOG, /* "packet_log" */
@ -32,6 +39,8 @@ enum upnpconfigoptions {
UPNPCLEANTHRESHOLD, /* clean_ruleset_threshold */
UPNPCLEANINTERVAL, /* clean_ruleset_interval */
UPNPENABLENATPMP, /* enable_natpmp */
UPNPPCPMINLIFETIME, /* minimum lifetime for PCP mapping */
UPNPPCPMAXLIFETIME, /* maximum lifetime for PCP mapping */
#ifdef USE_NETFILTER
UPNPFORWARDCHAIN,
UPNPNATCHAIN,

290
miniupnpd/pcp_msg_struct.h Normal file
View File

@ -0,0 +1,290 @@
/* $Id: pcp_msg_struct.h $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Peter Tatrai
Copyright (c) 2013 by Cisco Systems, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#define PCP_OPCODE_ANNOUNCE 0
#define PCP_OPCODE_MAP 1
#define PCP_OPCODE_PEER 2
#ifdef PCP_SADSCP
#define PCP_OPCODE_SADSCP 3
#endif
/* Possible response codes sent by server, as a result of client request*/
#define PCP_SUCCESS 0
#define PCP_ERR_UNSUPP_VERSION 1
/** The version number at the start of the PCP Request
* header is not recognized by this PCP server. This is a long
* lifetime error. This document describes PCP version 2.
*/
#define PCP_ERR_NOT_AUTHORIZED 2
/**The requested operation is disabled for this PCP
* client, or the PCP client requested an operation that cannot be
* fulfilled by the PCP server's security policy. This is a long
* lifetime error.
*/
#define PCP_ERR_MALFORMED_REQUEST 3
/**The request could not be successfully parsed.
* This is a long lifetime error.
*/
#define PCP_ERR_UNSUPP_OPCODE 4
/** Unsupported Opcode. This is a long lifetime error.
*/
#define PCP_ERR_UNSUPP_OPTION 5
/**Unsupported Option. This error only occurs if the
* Option is in the mandatory-to-process range. This is a long
* lifetime error.
*/
#define PCP_ERR_MALFORMED_OPTION 6
/**Malformed Option (e.g., appears too many times,
* invalid length). This is a long lifetime error.
*/
#define PCP_ERR_NETWORK_FAILURE 7
/**The PCP server or the device it controls are
* experiencing a network failure of some sort (e.g., has not
* obtained an External IP address). This is a short lifetime error.
*/
#define PCP_ERR_NO_RESOURCES 8
/**Request is well-formed and valid, but the server has
* insufficient resources to complete the requested operation at this
* time. For example, the NAT device cannot create more mappings at
* this time, is short of CPU cycles or memory, or is unable to
* handle the request due to some other temporary condition. The
* same request may succeed in the future. This is a system-wide
* error, different from USER_EX_QUOTA. This can be used as a catch-
* all error, should no other error message be suitable. This is a
* short lifetime error.
*/
#define PCP_ERR_UNSUPP_PROTOCOL 9
/**Unsupported transport protocol, e.g. SCTP in a
* NAT that handles only UDP and TCP. This is a long lifetime error.
*/
#define PCP_ERR_USER_EX_QUOTA 10
/** This attempt to create a new mapping would exceed
* this subscriber's port quota. This is a short lifetime error.
*/
#define PCP_ERR_CANNOT_PROVIDE_EXTERNAL 11
/** The suggested external port and/or
* external address cannot be provided. This error MUST only be
* returned for:
* * MAP requests that included the PREFER_FAILURE Option
* (normal MAP requests will return an available external port)
* * MAP requests for the SCTP protocol (PREFER_FAILURE is implied)
* * PEER requests
*/
#define PCP_ERR_ADDRESS_MISMATCH 12
/** The source IP address of the request packet does
* not match the contents of the PCP Client's IP Address field, due
* to an unexpected NAT on the path between the PCP client and the
* PCP-controlled NAT or firewall. This is a long lifetime error.
*/
#define PCP_ERR_EXCESSIVE_REMOTE_PEERS 13
/** The PCP server was not able to create the
* filters in this request. This result code MUST only be returned
* if the MAP request contained the FILTER Option. See Section 13.3
* for processing information. This is a long lifetime error.
*/
typedef enum pcp_options {
PCP_OPTION_3RD_PARTY = 1,
PCP_OPTION_PREF_FAIL = 2,
PCP_OPTION_FILTER = 3,
#ifdef PCP_FLOWP
PCP_OPTION_FLOW_PRIORITY = 4, /*TODO: change it to correct value*/
#endif
} pcp_options_t;
#ifdef WIN32
#pragma warning (push)
#pragma warning (disable:4200)
#endif // WIN32
#pragma pack(push, 1)
/* PCP common request header*/
typedef struct pcp_request {
uint8_t ver;
uint8_t r_opcode;
uint16_t reserved;
uint32_t req_lifetime;
uint32_t ip[4]; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint8_t next_data[0];
} pcp_request_t;
/* PCP common response header*/
typedef struct pcp_response {
uint8_t ver;
uint8_t r_opcode; /* R indicates Request (0) or Response (1)
Opcode is 7 bit value specifying operation MAP or PEER */
uint8_t reserved; /* reserved bits, must be 0 on transmission and must be ignored on reception */
uint8_t result_code; /* */
uint32_t lifetime; /* an unsigned 32-bit integer, in seconds {0, 2^32-1}*/
uint32_t epochtime; /* epoch indicates how long has PCP server had its current mappings
it increases by 1 every second */
uint32_t reserved1[3];/* For requests that were successfully parsed this must be sent as 0 */
uint8_t next_data[0];
} pcp_response_t;
typedef struct pcp_options_hdr {
uint8_t code; /* Most significant bit indicates if this option is mandatory (0) or optional (1) */
uint8_t reserved; /* MUST be set to 0 on transmission and MUST be ignored on reception */
uint16_t len; /* indicates the length of the enclosed data in octets (see RFC) */
uint8_t next_data[0]; /* */
} pcp_options_hdr_t;
/* same for both request and response */
typedef struct pcp_map_v2 {
uint32_t nonce[3];
uint8_t protocol;
uint8_t reserved[3];
uint16_t int_port;
uint16_t ext_port;
uint32_t ext_ip[4]; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint8_t next_data[0];
} pcp_map_v2_t;
/* same for both request and response */
typedef struct pcp_map_v1 {
uint8_t protocol;
uint8_t reserved[3];
uint16_t int_port;
uint16_t ext_port;
uint32_t ext_ip[4]; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint8_t next_data[0];
} pcp_map_v1_t;
/* same for both request and response */
typedef struct pcp_peer_v1 {
uint8_t protocol;
uint8_t reserved[3];
uint16_t int_port;
uint16_t ext_port;
uint32_t ext_ip[4]; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint16_t peer_port;
uint16_t reserved1;
uint32_t peer_ip[4];
uint8_t next_data[0];
} pcp_peer_v1_t;
/* same for both request and response */
typedef struct pcp_peer_v2 {
uint32_t nonce[3];
uint8_t protocol;
uint8_t reserved[3];
uint16_t int_port;
uint16_t ext_port;
uint32_t ext_ip[4]; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint16_t peer_port;
uint16_t reserved1;
uint32_t peer_ip[4];
uint8_t next_data[0];
} pcp_peer_v2_t;
#ifdef PCP_SADSCP
typedef struct pcp_sadscp_req {
uint32_t nonce[3];
uint8_t tolerance_fields;
uint8_t app_name_length;
char app_name[0];
} pcp_sadscp_req_t;
typedef struct pcp_sadscp_resp {
uint32_t nonce[3];
#define PCP_SADSCP_MASK ((1<<6)-1)
uint8_t a_r_dscp_value;
uint8_t reserved[3];
} pcp_sadscp_resp_t;
#endif
typedef struct pcp_prefer_fail_option {
uint8_t option;
uint8_t reserved;
uint16_t len;
uint8_t next_data[0];
} pcp_prefer_fail_option_t;
typedef struct pcp_3rd_party_option{
uint8_t option;
uint8_t reserved;
uint16_t len;
uint32_t ip[4];
uint8_t next_data[0];
} pcp_3rd_party_option_t;
#ifdef PCP_FLOWP
typedef struct pcp_flow_priority_option{
uint8_t option;
uint8_t reserved;
uint16_t len;
uint8_t dscp_up;
uint8_t dscp_down;
#define PCP_DSCP_MASK ((1<<6)-1)
uint8_t reserved2;
/* most significant bit is used for response */
uint8_t response_bit;
uint8_t next_data[0];
} pcp_flow_priority_option_t;
#endif
typedef struct pcp_filter_option {
uint8_t option;
uint8_t reserved1;
uint16_t len;
uint8_t reserved2;
uint8_t prefix_len;
uint16_t peer_port;
uint32_t peer_ip[4];
}pcp_filter_option_t;
#pragma pack(pop)
#ifdef WIN32
#pragma warning (pop)
#endif // WIN32

298
miniupnpd/pcplearndscp.c Normal file
View File

@ -0,0 +1,298 @@
/* $Id: pcplearndscp.c $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Miroslav Bagljas
Copyright (c) 2013 by Cisco Systems, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <syslog.h>
#include "upnpglobalvars.h"
#include "pcplearndscp.h"
#ifdef PCP_SADSCP
void
print_dscp(void) {
unsigned int i;
for (i=0; i < num_dscp_values; i++){
syslog(LOG_DEBUG, "Appname %*.s, del %d, loss %d, jitter %d, dscp %d",
dscp_values_list[i].app_name_len,
dscp_values_list[i].app_name, dscp_values_list[i].delay,
dscp_values_list[i].loss, dscp_values_list[i].jitter,
dscp_values_list[i].dscp_value
);
}
}
int
read_learn_dscp_line(struct dscp_values *dscpvalues, char *p)
{
char * q;
size_t len;
unsigned int sizeof_first_token = sizeof("set_learn_dscp") - 1;
int af_value;
int cs_value;
/* first token: (set_learn_dscp) skip it */
while(isspace(*p))
p++;
if(0 == memcmp(p, "set_learn_dscp", sizeof_first_token))
{
p += sizeof_first_token;
}
else
{
return -1;
}
while(isspace(*p))
p++;
/* second token: name of the application */
// if
if(!(*p == '"'))
return -1;
p++;
for(q = p; !(*q == '"'); q++);
len = q - p;
if (len != 0) {
dscpvalues->app_name = strndup(p, len);
} else {
dscpvalues->app_name = NULL;
}
dscpvalues->app_name_len = len;
p = q + 1;
/* third token: delay */
while(isspace(*p))
p++;
if(!isdigit(*p))
goto exit_err_and_cleanup;
for(q = p; isdigit(*q); q++);
if(isspace(*q))
{
*q = '\0';
dscpvalues->delay = (unsigned char)atoi(p);
if (dscpvalues->delay >= 3) {
fprintf(stderr, "Wrong delay value %d in \n", dscpvalues->delay);
fprintf(stderr, "Delay can be from set {0,1,2} 0=low delay, 1=medium delay, 2=high delay\n");
goto exit_err_and_cleanup;
}
}
else
{
goto exit_err_and_cleanup;
}
p = q + 1;
/* fourth token: loss */
while(isspace(*p))
p++;
if(!isdigit(*p))
goto exit_err_and_cleanup;
for(q = p; isdigit(*q); q++);
if(isspace(*q))
{
*q = '\0';
dscpvalues->loss = (unsigned char)atoi(p);
if (dscpvalues->loss >= 3) {
fprintf(stderr, "Wrong loss value %d \n", dscpvalues->loss);
fprintf(stderr, "Delay can be from set {0,1,2} 0=low loss, 1=medium loss, 2=high loss\n");
goto exit_err_and_cleanup;
}
}
else
{
goto exit_err_and_cleanup;
}
p = q + 1;
/* fifth token: jitter */
while(isspace(*p))
p++;
if(!isdigit(*p))
goto exit_err_and_cleanup;
for(q = p; isdigit(*q); q++);
if(isspace(*q))
{
*q = '\0';
dscpvalues->jitter = (unsigned char)atoi(p);
if (dscpvalues->jitter >= 3) {
fprintf(stderr, "Wrong jitter value %d \n", dscpvalues->jitter);
fprintf(stderr, "Delay can be from set {0,1,2} 0=low jitter, 1=medium jitter, 2=high jitter \n");
goto exit_err_and_cleanup;
}
}
else
{
goto exit_err_and_cleanup;
}
p = q + 1;
while(isspace(*p))
p++;
/*{
}*/
p = q + 1;
/* sixth token: DSCP value */
while(isspace(*p))
p++;
if(!isdigit(*p) && !( toupper(*p) == 'A' && toupper(*(p+1)) == 'F') &&
!( toupper(*p) == 'C' && toupper(*(p+1)) == 'S') &&
!( toupper(*p) == 'E' && toupper(*(p+1)) == 'F')
)
goto exit_err_and_cleanup;
// for(q = p; isdigit(*q) || (toupper(*q) == 'A') || (toupper(*q) == 'F'); q++);
for(q = p; isdigit(*q) || isalpha(*q); q++);
if(isspace(*q) || *q == '\0')
{
*q = '\0';
if (toupper(*p) == 'A' && toupper(*(p+1)) == 'F'){
p = p+2;
if (*p == '\0') {
dscpvalues->dscp_value = 0;
}
else if (!isdigit(*p)) {
goto exit_err_and_cleanup;
}
else {
af_value = atoi(p);
switch(af_value) {
case 11:
dscpvalues->dscp_value = 10;
break;
case 12:
dscpvalues->dscp_value = 12;
break;
case 13:
dscpvalues->dscp_value = 14;
break;
case 21:
dscpvalues->dscp_value = 18;
break;
case 22:
dscpvalues->dscp_value = 20;
break;
case 23:
dscpvalues->dscp_value = 22;
break;
case 31:
dscpvalues->dscp_value = 26;
break;
case 32:
dscpvalues->dscp_value = 28;
break;
case 33:
dscpvalues->dscp_value = 30;
break;
case 41:
dscpvalues->dscp_value = 34;
break;
case 42:
dscpvalues->dscp_value = 36;
break;
case 43:
dscpvalues->dscp_value = 38;
break;
default:
fprintf(stderr, "Unknown AF value %u \n", af_value);
goto exit_err_and_cleanup;
}
}
}
else if (toupper(*p) == 'C' && toupper(*(p+1)) == 'S'){
p=p+2;
if (*p == '\0') {
dscpvalues->dscp_value = 0;
}
else if (!isdigit(*p)) {
fprintf(stderr, "Not digit after CS but %c \n", *p);
goto exit_err_and_cleanup;
}
else {
cs_value = atoi(p);
switch(cs_value) {
case 1:
dscpvalues->dscp_value = 8;
break;
case 2:
dscpvalues->dscp_value = 16;
break;
case 3:
dscpvalues->dscp_value = 24;
break;
case 4:
dscpvalues->dscp_value = 32;
break;
case 5:
dscpvalues->dscp_value = 40;
break;
case 6:
dscpvalues->dscp_value = 48;
break;
case 7:
dscpvalues->dscp_value = 56;
break;
default:
fprintf(stderr, "Unknown CS value %d \n", cs_value);
goto exit_err_and_cleanup;
}
}
}
else if (toupper(*p) == 'E' && toupper(*(p+1)) == 'F'){
dscpvalues->dscp_value = 46;
}
else {
dscpvalues->dscp_value = (unsigned char)atoi(p);
}
}
else
{
goto exit_err_and_cleanup;
}
return 0;
exit_err_and_cleanup:
free(dscpvalues->app_name);
dscpvalues->app_name = NULL;
dscpvalues->app_name_len = 0;
return -1;
}
#endif

51
miniupnpd/pcplearndscp.h Normal file
View File

@ -0,0 +1,51 @@
/* $Id: pcplearndscp.h $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Miroslav Bagljas
Copyright (c) 2013 by Cisco Systems, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PCPLEARNDSCP_H_INCLUDED
#define PCPLEARNDSCP_H_INCLUDED
struct dscp_values {
char *app_name;
unsigned int app_name_len;
unsigned char delay;
unsigned char loss;
unsigned char jitter;
unsigned char dscp_value;
};
// #set_learn_dscp "Webex" 1 1 1 34
int
read_learn_dscp_line(struct dscp_values *dscpvalues, char *p);
#endif // PCPLEARNDSCP_H_INCLUDED

1339
miniupnpd/pcpserver.c Normal file

File diff suppressed because it is too large Load Diff

45
miniupnpd/pcpserver.h Normal file
View File

@ -0,0 +1,45 @@
/* $Id: pcpserver.h $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Peter Tatrai
Copyright (c) 2013 by Cisco Systems, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PCPSERVER_H_INCLUDED
#define PCPSERVER_H_INCLUDED
#define PCP_MIN_LEN 24
#define PCP_MAX_LEN 1100
/*
* returns 0 upon success 1 otherwise
*/
int ProcessIncomingPCPPacket(int s, unsigned char *msg_buff, int len, \
struct sockaddr_in *senderaddr);
#endif /* PCPSERVER_H_INCLUDED */

View File

@ -1,6 +1,6 @@
/* */
/* MiniUPnP project
* (c) 2007-2012 Thomas Bernard
* (c) 2007-2013 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 */
@ -21,6 +21,8 @@
#include "getifaddr.h"
#include "portinuse.h"
#include "netfilter/iptcrdr.h"
/* Hardcoded for now. Ideally would come from .conf file */
char *chains_to_check[] = { "PREROUTING" , 0 };
@ -30,15 +32,15 @@ int port_in_use(const char *if_name, unsigned eport, int proto, const char *iadd
FILE *f;
int found = 0;
char ip_addr_str[INET_ADDRSTRLEN];
struct in_addr ip_addr = { .s_addr = 0 };
struct in_addr ip_addr;
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);
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, %8X",
(proto==IPPROTO_TCP)?"tcp":"udp", eport, if_name, ip_addr_str, (unsigned)ip_addr.s_addr);

View File

@ -1,11 +1,15 @@
/* $Id: testgetifaddr.c,v 1.4 2012/03/05 20:36:17 nanard Exp $ */
/* $Id: testgetifaddr.c,v 1.7 2013/04/27 15:38:57 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdio.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "getifaddr.h"
#if defined(__sun)
@ -14,17 +18,21 @@
#endif
int main(int argc, char * * argv) {
char addr[64];
char str_addr[64];
struct in_addr addr;
struct in_addr mask;
if(argc < 2) {
fprintf(stderr, "Usage:\t%s interface_name\n", argv[0]);
return 1;
}
openlog("testgetifaddr", LOG_CONS|LOG_PERROR, LOG_USER);
if(getifaddr(argv[1], addr, sizeof(addr)) < 0) {
if(getifaddr(argv[1], str_addr, sizeof(str_addr), &addr, &mask) < 0) {
fprintf(stderr, "Cannot get address for interface %s.\n", argv[1]);
return 1;
}
printf("Interface %s has IP address %s.\n", argv[1], addr);
printf("Interface %s has IP address %s.\n", argv[1], str_addr);
printf("addr=%s ", inet_ntoa(addr));
printf("mask=%s\n", inet_ntoa(mask));
return 0;
}

View File

@ -1,7 +1,7 @@
/* $Id: testupnpdescgen.c,v 1.29 2012/04/30 21:08:00 nanard Exp $ */
/* $Id: testupnpdescgen.c,v 1.30 2013/06/13 13:21:30 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -16,13 +16,23 @@
#include "macros.h"
#include "config.h"
#include "upnpdescgen.h"
#include "upnpdescstrings.h"
char uuidvalue[] = "uuid:12345678-0000-0000-0000-00000000abcd";
char uuidvalue_igd[] = "uuid:12345678-0000-0000-0000-000000abcd01";
char uuidvalue_wan[] = "uuid:12345678-0000-0000-0000-000000abcd02";
char uuidvalue_wcd[] = "uuid:12345678-0000-0000-0000-000000abcd03";
char serialnumber[] = "12345678";
char modelnumber[] = "1";
char presentationurl[] = "http://192.168.0.1:8080/";
/*char presentationurl[] = "";*/
#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
char friendly_name[] = OS_NAME " router";
char manufacturer_name[] = ROOTDEV_MANUFACTURER;
char manufacturer_url[] = ROOTDEV_MANUFACTURERURL;
char model_name[] = ROOTDEV_MODELNAME;
char model_description[] = ROOTDEV_MODELDESCRIPTION;
char model_url[] = ROOTDEV_MODELURL;
#endif
char * use_ext_ip_addr = NULL;
const char * ext_if_name = "eth0";

View File

@ -1,7 +1,7 @@
/* $Id: upnpdescgen.c,v 1.71 2012/10/04 22:08:08 nanard Exp $ */
/* $Id: upnpdescgen.c,v 1.74 2013/06/13 13:21:30 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -145,16 +145,27 @@ static const struct XMLElt rootDesc[] =
/* 5 */
{"/deviceType", DEVICE_TYPE_IGD},
/* urn:schemas-upnp-org:device:InternetGatewayDevice:1 or 2 */
#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
{"/friendlyName", friendly_name/*ROOTDEV_FRIENDLYNAME*/}, /* required */
{"/manufacturer", ROOTDEV_MANUFACTURER}, /* required */
{"/manufacturer", manufacturer_name/*ROOTDEV_MANUFACTURER*/}, /* required */
/* 8 */
{"/manufacturerURL", manufacturer_url/*ROOTDEV_MANUFACTURERURL*/}, /* optional */
{"/modelDescription", model_description/*ROOTDEV_MODELDESCRIPTION*/}, /* recommended */
{"/modelName", model_name/*ROOTDEV_MODELNAME*/}, /* required */
{"/modelNumber", modelnumber},
{"/modelURL", model_url/*ROOTDEV_MODELURL*/},
#else
{"/friendlyName", ROOTDEV_FRIENDLYNAME}, /* required */
{"/manufacturer", ROOTDEV_MANUFACTURER}, /* required */
/* 8 */
{"/manufacturerURL", ROOTDEV_MANUFACTURERURL}, /* optional */
{"/modelDescription", ROOTDEV_MODELDESCRIPTION}, /* recommended */
{"/modelName", ROOTDEV_MODELNAME}, /* required */
{"/modelNumber", modelnumber},
{"/modelURL", ROOTDEV_MODELURL},
#endif
{"/serialNumber", serialnumber},
{"/UDN", uuidvalue}, /* required */
{"/UDN", uuidvalue_igd}, /* required */
/* see if /UPC is needed. */
#ifdef ENABLE_6FC_SERVICE
#define SERVICES_OFFSET 63
@ -201,7 +212,7 @@ static const struct XMLElt rootDesc[] =
{"/modelNumber", WANDEV_MODELNUMBER},
{"/modelURL", WANDEV_MODELURL},
{"/serialNumber", serialnumber},
{"/UDN", uuidvalue},
{"/UDN", uuidvalue_wan},
{"/UPC", WANDEV_UPC}, /* UPC (=12 digit barcode) is optional */
/* 30 */
{"serviceList", INITHELPER(32,1)},
@ -229,7 +240,7 @@ static const struct XMLElt rootDesc[] =
{"/modelNumber", WANCDEV_MODELNUMBER},
{"/modelURL", WANCDEV_MODELURL},
{"/serialNumber", serialnumber},
{"/UDN", uuidvalue},
{"/UDN", uuidvalue_wcd},
{"/UPC", WANCDEV_UPC}, /* UPC (=12 digit Barcode) is optional */
#ifdef ENABLE_6FC_SERVICE
{"serviceList", INITHELPER(51,2)},
@ -1134,7 +1145,7 @@ genDP(int * len)
#ifdef ENABLE_EVENTS
static char *
genEventVars(int * len, const struct serviceDesc * s, const char * servns)
genEventVars(int * len, const struct serviceDesc * s)
{
char tmp[16];
const struct stateVar * v;
@ -1146,15 +1157,13 @@ genEventVars(int * len, const struct serviceDesc * s, const char * servns)
return NULL;
*len = 0;
v = s->serviceStateTable;
str = strcat_str(str, len, &tmplen, "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"");
str = strcat_str(str, len, &tmplen, servns);
str = strcat_str(str, len, &tmplen, "\">");
str = strcat_str(str, len, &tmplen, "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">");
while(v->name) {
if(v->itype & 0x80) {
str = strcat_str(str, len, &tmplen, "<e:property><s:");
str = strcat_str(str, len, &tmplen, "<e:property><");
str = strcat_str(str, len, &tmplen, v->name);
str = strcat_str(str, len, &tmplen, ">");
/*printf("<e:property><s:%s>", v->name);*/
/*printf("<e:property><%s>", v->name);*/
switch(v->ieventvalue) {
case 0:
break;
@ -1198,7 +1207,7 @@ genEventVars(int * len, const struct serviceDesc * s, const char * servns)
str = strcat_str(str, len, &tmplen, use_ext_ip_addr);
else {
char ext_ip_addr[INET_ADDRSTRLEN];
if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) {
if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, NULL, NULL) < 0) {
str = strcat_str(str, len, &tmplen, "0.0.0.0");
} else {
str = strcat_str(str, len, &tmplen, ext_ip_addr);
@ -1207,7 +1216,7 @@ genEventVars(int * len, const struct serviceDesc * s, const char * servns)
break;
case DEFAULTCONNECTIONSERVICE_MAGICALVALUE:
/* DefaultConnectionService magical value */
str = strcat_str(str, len, &tmplen, uuidvalue);
str = strcat_str(str, len, &tmplen, uuidvalue_wcd);
#ifdef IGD_V2
str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:2,urn:upnp-org:serviceId:WANIPConn1");
#else
@ -1217,10 +1226,10 @@ genEventVars(int * len, const struct serviceDesc * s, const char * servns)
default:
str = strcat_str(str, len, &tmplen, upnpallowedvalues[v->ieventvalue]);
}
str = strcat_str(str, len, &tmplen, "</s:");
str = strcat_str(str, len, &tmplen, "</");
str = strcat_str(str, len, &tmplen, v->name);
str = strcat_str(str, len, &tmplen, "></e:property>");
/*printf("</s:%s></e:property>\n", v->name);*/
/*printf("</%s></e:property>\n", v->name);*/
}
v++;
}
@ -1238,16 +1247,14 @@ char *
getVarsWANIPCn(int * l)
{
return genEventVars(l,
&scpdWANIPCn,
SERVICE_TYPE_WANIPC);
&scpdWANIPCn);
}
char *
getVarsWANCfg(int * l)
{
return genEventVars(l,
&scpdWANCfg,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1");
&scpdWANCfg);
}
#ifdef ENABLE_L3F_SERVICE
@ -1255,8 +1262,7 @@ char *
getVarsL3F(int * l)
{
return genEventVars(l,
&scpdL3F,
"urn:schemas-upnp-org:service:Layer3Forwarding:1");
&scpdL3F);
}
#endif
@ -1265,8 +1271,7 @@ char *
getVars6FC(int * l)
{
return genEventVars(l,
&scpd6FC,
"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1");
&scpd6FC);
}
#endif
@ -1275,8 +1280,7 @@ char *
getVarsDP(int * l)
{
return genEventVars(l,
&scpdDP,
"urn:schemas-upnp-org:service:DeviceProtection:1");
&scpdDP);
}
#endif

View File

@ -1,7 +1,7 @@
/* $Id: upnpdescstrings.h,v 1.8 2012/09/27 16:00:10 nanard Exp $ */
/* miniupnp project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the coditions detailed in
* the LICENCE file provided within the distribution */
#ifndef UPNPDESCSTRINGS_H_INCLUDED
@ -10,7 +10,7 @@
#include "config.h"
/* strings used in the root device xml description */
/*#define ROOTDEV_FRIENDLYNAME OS_NAME " router"*/
#define ROOTDEV_FRIENDLYNAME OS_NAME " router"
#define ROOTDEV_MANUFACTURER OS_NAME
#define ROOTDEV_MANUFACTURERURL OS_URL
#define ROOTDEV_MODELNAME OS_NAME " router"

View File

@ -1,7 +1,7 @@
/* $Id: upnpevents.c,v 1.26 2012/10/04 22:11:56 nanard Exp $ */
/* $Id: upnpevents.c,v 1.27 2013/06/13 13:21:30 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2008-2012 Thomas Bernard
* (c) 2008-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -110,7 +110,7 @@ newSubscriber(const char * eventurl, const char * callback, int callbacklen)
tmp->callback[callbacklen] = '\0';
/* make a dummy uuid */
/* TODO: improve that */
strncpy(tmp->uuid, uuidvalue, sizeof(tmp->uuid));
strncpy(tmp->uuid, uuidvalue_igd, sizeof(tmp->uuid));
tmp->uuid[sizeof(tmp->uuid)-1] = '\0';
snprintf(tmp->uuid+37, 5, "%04lx", random() & 0xffff);
return tmp;

View File

@ -1,4 +1,4 @@
/* $Id: upnpglobalvars.c,v 1.29 2012/04/26 14:01:16 nanard Exp $ */
/* $Id: upnpglobalvars.c,v 1.30 2013/06/13 13:21:30 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
@ -10,6 +10,7 @@
#include "config.h"
#include "upnpglobalvars.h"
#include "upnpdescstrings.h"
/* network interface for internet */
const char * ext_if_name = 0;
@ -32,11 +33,16 @@ unsigned long upstream_bitrate = 0;
/* startup time */
time_t startup_time = 0;
unsigned long int min_lifetime = 120;
unsigned long int max_lifetime = 86400;
int runtime_flags = 0;
const char * pidfilename = "/var/run/miniupnpd.pid";
char uuidvalue[] = "uuid:00000000-0000-0000-0000-000000000000";
char uuidvalue_igd[] = "uuid:00000000-0000-0000-0000-000000000000";
char uuidvalue_wan[] = "uuid:00000000-0000-0000-0000-000000000000";
char uuidvalue_wcd[] = "uuid:00000000-0000-0000-0000-000000000000";
char serialnumber[SERIALNUMBER_MAX_LEN] = "00000000";
char modelnumber[MODELNUMBER_MAX_LEN] = "1";
@ -45,9 +51,26 @@ char modelnumber[MODELNUMBER_MAX_LEN] = "1";
* http://nnn.nnn.nnn.nnn:ppppp/ => max 30 bytes including terminating 0 */
char presentationurl[PRESENTATIONURL_MAX_LEN];
#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
/* friendly name for root devices in XML description */
char friendly_name[FRIENDLY_NAME_MAX_LEN] = OS_NAME " router";
/* manufacturer name for root devices in XML description */
char manufacturer_name[MANUFACTURER_NAME_MAX_LEN] = ROOTDEV_MANUFACTURER;
/* manufacturer url for root devices in XML description */
char manufacturer_url[MANUFACTURER_URL_MAX_LEN] = ROOTDEV_MANUFACTURERURL;
/* model name for root devices in XML description */
char model_name[MODEL_NAME_MAX_LEN] = ROOTDEV_MODELNAME;
/* model description for root devices in XML description */
char model_description[MODEL_DESCRIPTION_MAX_LEN] = ROOTDEV_MODELDESCRIPTION;
/* model url for root devices in XML description */
char model_url[MODEL_URL_MAX_LEN] = ROOTDEV_MODELURL;
#endif
/* UPnP permission rules : */
struct upnpperm * upnppermlist = 0;
unsigned int num_upnpperm = 0;
@ -59,6 +82,10 @@ unsigned int nextnatpmptoclean_timestamp = 0;
unsigned short nextnatpmptoclean_eport = 0;
unsigned short nextnatpmptoclean_proto = 0;
#endif
#ifdef PCP_SADSCP
struct dscp_values* dscp_values_list = 0;
unsigned int num_dscp_values = 0;
#endif //PCP_SADSCP
#endif
/* For automatic removal of expired rules (with LeaseDuration) */
@ -74,6 +101,7 @@ const char * tag = 0;
/* chain name to use, both in the nat table
* and the filter table */
const char * miniupnpd_nat_chain = "MINIUPNPD";
const char * miniupnpd_peer_chain = "MINIUPNPD-PCP-PEER";
const char * miniupnpd_forward_chain = "MINIUPNPD";
#ifdef ENABLE_6FC_SERVICE
const char * miniupnpd_v6_filter_chain = "MINIUPNPD";

View File

@ -1,4 +1,4 @@
/* $Id: upnpglobalvars.h,v 1.33 2012/04/26 14:01:16 nanard Exp $ */
/* $Id: upnpglobalvars.h,v 1.35 2013/06/13 13:21:30 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
@ -32,6 +32,10 @@ extern unsigned long upstream_bitrate;
/* statup time */
extern time_t startup_time;
extern unsigned long int min_lifetime;
extern unsigned long int max_lifetime;
/* runtime boolean flags */
extern int runtime_flags;
#define LOGPACKETSMASK 0x0001
@ -54,7 +58,9 @@ extern int runtime_flags;
extern const char * pidfilename;
extern char uuidvalue[];
extern char uuidvalue_igd[]; /* uuid of root device (IGD) */
extern char uuidvalue_wan[]; /* uuid of WAN Device */
extern char uuidvalue_wcd[]; /* uuid of WAN Connection Device */
#define SERIALNUMBER_MAX_LEN (10)
extern char serialnumber[];
@ -65,9 +71,26 @@ extern char modelnumber[];
#define PRESENTATIONURL_MAX_LEN (64)
extern char presentationurl[];
#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
#define FRIENDLY_NAME_MAX_LEN (64)
extern char friendly_name[];
#define MANUFACTURER_NAME_MAX_LEN (64)
extern char manufacturer_name[];
#define MANUFACTURER_URL_MAX_LEN (64)
extern char manufacturer_url[];
#define MODEL_NAME_MAX_LEN (64)
extern char model_name[];
#define MODEL_DESCRIPTION_MAX_LEN (64)
extern char model_description[];
#define MODEL_URL_MAX_LEN (64)
extern char model_url[];
#endif
/* UPnP permission rules : */
extern struct upnpperm * upnppermlist;
extern unsigned int num_upnpperm;
@ -79,6 +102,10 @@ extern unsigned int nextnatpmptoclean_timestamp;
extern unsigned short nextnatpmptoclean_eport;
extern unsigned short nextnatpmptoclean_proto;
#endif
#ifdef PCP_SADSCP
extern struct dscp_values* dscp_values_list;
extern unsigned int num_dscp_values;
#endif
#endif
/* For automatic removal of expired rules (with LeaseDuration) */
@ -93,6 +120,7 @@ extern const char * tag;
#ifdef USE_NETFILTER
extern const char * miniupnpd_nat_chain;
extern const char * miniupnpd_peer_chain;
extern const char * miniupnpd_forward_chain;
#ifdef ENABLE_6FC_SERVICE
extern const char * miniupnpd_v6_filter_chain;

View File

@ -510,6 +510,32 @@ get_upnp_rules_state_list(int max_rules_number_target)
if(!tmp)
break;
}
#ifdef PCP_PEER
i=0;
while(get_peer_rule_by_index(i, /*ifname*/0, &tmp->eport, 0, 0,
&iport, &proto, 0, 0, 0,0,0, &timestamp,
&tmp->packets, &tmp->bytes) >= 0)
{
tmp->to_remove = 0;
if(timestamp > 0) {
/* need to remove this port mapping ? */
if(timestamp <= (unsigned int)current_time)
tmp->to_remove = 1;
else if((nextruletoclean_timestamp <= (unsigned int)current_time)
|| (timestamp < nextruletoclean_timestamp))
nextruletoclean_timestamp = timestamp;
}
tmp->proto = (short)proto;
/* add tmp to list */
tmp->next = list;
list = tmp;
/* prepare next iteration */
i++;
tmp = malloc(sizeof(struct rule_state));
if(!tmp)
break;
}
#endif
free(tmp);
/* remove the redirections that need to be removed */
for(p = &list, tmp = list; tmp; tmp = *p)

View File

@ -1,7 +1,7 @@
/* $Id: upnpreplyparse.c,v 1.11 2011/02/07 16:17:06 nanard Exp $ */
/* $Id: upnpreplyparse.c,v 1.15 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -15,18 +15,55 @@
static void
NameValueParserStartElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValueParserData * data = (struct NameValueParserData *)d;
data->topelt = 1;
if(l>63)
l = 63;
memcpy(data->curelt, name, l);
data->curelt[l] = '\0';
data->cdata = NULL;
data->cdatalen = 0;
}
static void
NameValueParserEndElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
(void)name;
(void)l;
if(!data->topelt)
return;
if(strcmp(data->curelt, "NewPortListing") != 0)
{
int l;
/* standard case. Limited to n chars strings */
l = data->cdatalen;
nv = malloc(sizeof(struct NameValue));
if(l>=(int)sizeof(nv->value))
l = sizeof(nv->value) - 1;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
if(data->cdata != NULL)
{
memcpy(nv->value, data->cdata, l);
nv->value[l] = '\0';
}
else
{
nv->value[0] = '\0';
}
LIST_INSERT_HEAD( &(data->head), nv, entries);
}
data->cdata = NULL;
data->cdatalen = 0;
data->topelt = 0;
}
static void
NameValueParserGetData(void * d, const char * datas, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
if(strcmp(data->curelt, "NewPortListing") == 0)
{
/* specific case for NewPortListing which is a XML Document */
@ -42,15 +79,9 @@ NameValueParserGetData(void * d, const char * datas, int l)
}
else
{
/* standard case. Limited to 63 chars strings */
nv = malloc(sizeof(struct NameValue));
if(l>63)
l = 63;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
memcpy(nv->value, datas, l);
nv->value[l] = '\0';
LIST_INSERT_HEAD( &(data->head), nv, entries);
/* standard case. */
data->cdata = datas;
data->cdatalen = l;
}
}
@ -67,7 +98,7 @@ ParseNameValue(const char * buffer, int bufsize,
parser.xmlsize = bufsize;
parser.data = data;
parser.starteltfunc = NameValueParserStartElt;
parser.endeltfunc = 0;
parser.endeltfunc = NameValueParserEndElt;
parser.datafunc = NameValueParserGetData;
parser.attfunc = 0;
parsexml(&parser);

View File

@ -1,7 +1,7 @@
/* $Id: upnpreplyparse.h,v 1.12 2012/01/21 13:30:33 nanard Exp $ */
/* $Id: upnpreplyparse.h,v 1.17 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -21,7 +21,7 @@ extern "C" {
struct NameValue {
LIST_ENTRY(NameValue) entries;
char name[64];
char value[64];
char value[128];
};
struct NameValueParserData {
@ -29,6 +29,9 @@ struct NameValueParserData {
char curelt[64];
char * portListing;
int portListingLength;
int topelt;
const char * cdata;
int cdatalen;
};
/* ParseNameValue() */
@ -45,10 +48,12 @@ char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name);
#if 0
/* GetValueFromNameValueListIgnoreNS() */
char *
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
const char * Name);
#endif
/* DisplayNameValueList() */
#ifdef DEBUG

View File

@ -1,12 +1,13 @@
/* $Id: upnpsoap.c,v 1.114 2013/02/06 12:40:25 nanard Exp $ */
/* $Id: upnpsoap.c,v 1.119 2013/08/19 16:16:00 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
@ -191,7 +192,7 @@ GetCommonLinkProperties(struct upnphttp * h, const char * action)
if(upstream_bitrate == 0) upstream_bitrate = data.baudrate;
}
}
if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) {
if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, NULL, NULL) < 0) {
status = "Down";
}
bodylen = snprintf(body, sizeof(body), resp,
@ -269,7 +270,7 @@ GetExternalIPAddress(struct upnphttp * h, const char * action)
{
strncpy(ext_ip_addr, use_ext_ip_addr, INET_ADDRSTRLEN);
}
else if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0)
else if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, NULL, NULL) < 0)
{
syslog(LOG_ERR, "Failed to get ip address for interface %s",
ext_if_name);
@ -409,6 +410,14 @@ AddPortMapping(struct upnphttp * h, const char * action)
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);
@ -794,9 +803,10 @@ GetGenericPortMappingEntry(struct upnphttp * h, const char * action)
"<NewLeaseDuration>%u</NewLeaseDuration>"
"</u:%sResponse>";
int index = 0;
long int index = 0;
unsigned short eport, iport;
const char * m_index;
char * endptr;
char protocol[4], iaddr[32];
char desc[64];
char rhost[40];
@ -812,13 +822,27 @@ GetGenericPortMappingEntry(struct upnphttp * h, const char * action)
SoapError(h, 402, "Invalid Args");
return;
}
errno = 0; /* To distinguish success/failure after call */
index = strtol(m_index, &endptr, 10);
if((errno == ERANGE && (index == LONG_MAX || index == LONG_MIN))
|| (errno != 0 && index == 0) || (m_index == endptr))
{
/* should condition (*endptr != '\0') be also an error ? */
if(m_index == endptr)
syslog(LOG_WARNING, "%s: no digits were found in <%s>",
"GetGenericPortMappingEntry", "NewPortMappingIndex");
else
syslog(LOG_WARNING, "%s: strtol('%s'): %m",
"GetGenericPortMappingEntry", m_index);
ClearNameValueList(&data);
SoapError(h, 402, "Invalid Args");
return;
}
index = (int)atoi(m_index);
syslog(LOG_INFO, "%s: index=%d", action, index);
syslog(LOG_INFO, "%s: index=%d", action, (int)index);
rhost[0] = '\0';
r = upnp_get_redirection_infos_by_index(index, &eport, protocol, &iport,
r = upnp_get_redirection_infos_by_index((int)index, &eport, protocol, &iport,
iaddr, sizeof(iaddr),
desc, sizeof(desc),
rhost, sizeof(rhost),
@ -1022,8 +1046,12 @@ SetDefaultConnectionService(struct upnphttp * h, const char * action)
* 721 InvalidServiceID
* 723 InvalidConnServiceSelection */
#ifdef UPNP_STRICT
if(0 != memcmp(uuidvalue, p, sizeof("uuid:00000000-0000-0000-0000-000000000000") - 1)) {
char * service;
service = strchr(p, ',');
if(0 != memcmp(uuidvalue_wcd, p, sizeof("uuid:00000000-0000-0000-0000-000000000000") - 1)) {
SoapError(h, 720, "InvalidDeviceUUID");
} else if(service == NULL || 0 != strcmp(service+1, SERVICE_ID_WANIPC)) {
SoapError(h, 721, "InvalidServiceID");
} else
#endif
{
@ -1053,7 +1081,7 @@ GetDefaultConnectionService(struct upnphttp * h, const char * action)
int bodylen;
bodylen = snprintf(body, sizeof(body), resp,
action, uuidvalue, action);
action, uuidvalue_wcd, action);
BuildSendAndCloseSoapResp(h, body, bodylen);
}
#endif

View File

@ -1,4 +1,4 @@
/* $Id: upnputils.c,v 1.6 2013/02/06 10:50:04 nanard Exp $ */
/* $Id: upnputils.c,v 1.7 2013/04/20 09:03:18 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
@ -114,8 +114,13 @@ get_lan_for_peer(const struct sockaddr * peer)
else
{
int index = -1;
if(get_src_for_route_to(peer, NULL, NULL, &index) < 0)
return NULL;
if(peer6->sin6_scope_id > 0)
index = (int)peer6->sin6_scope_id;
else
{
if(get_src_for_route_to(peer, NULL, NULL, &index) < 0)
return NULL;
}
syslog(LOG_DEBUG, "%s looking for LAN interface index=%d",
"get_lan_for_peer()", index);
for(lan_addr = lan_addrs.lh_first;