Merge branch 'master' into search_all
This commit is contained in:
commit
370d568715
2
README
2
README
|
@ -42,4 +42,4 @@ Thanks to :
|
|||
* Chiaki Ishikawa
|
||||
* Jardel Weyrich
|
||||
* Leah X. Schmidt
|
||||
|
||||
* Leo Moll
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -20,4 +20,6 @@ _jnaerator.*
|
|||
out.errors.txt
|
||||
jnaerator-*.jar
|
||||
miniupnpc.h.bak
|
||||
testupnpreplyparse
|
||||
validateupnpreplyparse
|
||||
listdevices
|
||||
|
|
|
@ -1,6 +1,35 @@
|
|||
$Id: Changelog.txt,v 1.181 2013/02/11 10:31:17 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $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/
|
||||
|
@ -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
|
||||
|
@ -81,12 +88,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
|
||||
|
||||
|
@ -133,7 +140,7 @@ all: $(LIBRARY) $(EXECUTABLES)
|
|||
|
||||
test: check
|
||||
|
||||
check: validateminixml validateminiwget
|
||||
check: validateminixml validateminiwget validateupnpreplyparse
|
||||
|
||||
everything: all $(EXECUTABLES_ADDTESTS)
|
||||
|
||||
|
@ -161,6 +168,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
|
||||
|
@ -221,10 +233,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 $@ $^
|
||||
|
||||
listdevices: listdevices.o $(LIBRARY) $(LDLIBS)
|
||||
|
@ -243,17 +255,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
|
||||
|
|
|
@ -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);
|
||||
|
|
@ -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 */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $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
|
||||
|
@ -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'
|
||||
|
@ -900,7 +915,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.
|
||||
*/
|
||||
|
@ -913,11 +928,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
|
||||
|
@ -925,6 +943,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)
|
||||
|
@ -933,41 +952,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') {
|
||||
|
@ -985,7 +1021,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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -87,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
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
NewRemoteHost=
|
||||
NewExternalPort=123
|
||||
NewProtocol=TCP
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
NewExternalIPAddress=1.2.3.4
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1 @@
|
|||
NewDefaultConnectionService=uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID
|
|
@ -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>
|
|
@ -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.
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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')
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,51 @@
|
|||
$Id: Changelog.txt,v 1.331 2013/02/11 10:37:06 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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile.linux,v 1.76 2013/02/07 15:56:10 nanard Exp $
|
||||
# $Id: Makefile.linux,v 1.78 2013/05/03 09:30:33 nanard Exp $
|
||||
# MiniUPnP project
|
||||
# (c) 2006-2013 Thomas Bernard
|
||||
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
|
@ -45,15 +45,35 @@ MANINSTALLDIR = $(INSTALLPREFIX)/share/man/man8
|
|||
BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
|
||||
upnpreplyparse.o minixml.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
|
||||
|
@ -115,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 \
|
||||
|
@ -157,6 +185,7 @@ install: miniupnpd miniupnpd.8 miniupnpd.conf genuuid \
|
|||
|
||||
# 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
|
||||
|
@ -211,7 +240,7 @@ 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,14 +249,17 @@ minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h
|
|||
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
|
||||
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 upnpglobalvars.h upnppermissions.h
|
||||
upnputils.o: miniupnpdtypes.h getroute.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
|
||||
|
@ -238,7 +270,8 @@ 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
|
||||
testupnpdescgen.o: getifaddr.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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
@ -96,7 +96,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) */
|
||||
|
@ -118,20 +118,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 */
|
||||
|
@ -140,14 +141,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);
|
||||
|
@ -172,7 +193,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 */
|
||||
|
@ -244,7 +265,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,
|
||||
|
@ -306,7 +327,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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
@ -417,6 +464,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
|
||||
|
@ -459,7 +620,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;
|
||||
|
@ -576,22 +737,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;
|
||||
|
@ -602,15 +875,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;
|
||||
|
@ -621,10 +904,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;
|
||||
}
|
||||
|
||||
|
@ -652,6 +945,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
|
||||
|
@ -739,11 +1074,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);
|
||||
|
@ -771,6 +1106,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)
|
||||
|
@ -800,11 +1255,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);
|
||||
|
|
|
@ -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,24 @@ 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);
|
||||
|
||||
/* for debug */
|
||||
int
|
||||
list_redirect_rule(const char * ifname);
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
×tamp,
|
||||
&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;
|
||||
}
|
||||
|
|
@ -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),
|
||||
×tamp,
|
||||
&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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,24 @@
|
|||
#include "macros.h"
|
||||
#include "config.h"
|
||||
#include "upnpdescgen.h"
|
||||
#include "upnpdescstrings.h"
|
||||
#include "getifaddr.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";
|
||||
|
@ -32,9 +43,11 @@ int ipv6fc_firewall_enabled = 1;
|
|||
int ipv6fc_inbound_pinhole_allowed = 1;
|
||||
#endif
|
||||
|
||||
int getifaddr(const char * ifname, char * buf, int len)
|
||||
int getifaddr(const char * ifname, char * buf, int len, struct in_addr * addr, struct in_addr * mask)
|
||||
{
|
||||
UNUSED(ifname);
|
||||
UNUSED(addr);
|
||||
UNUSED(mask);
|
||||
strncpy(buf, "1.2.3.4", len);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -505,6 +505,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, ×tamp,
|
||||
&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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue