Merge remote branch 'origin/master' into portinuse

Conflicts:
	miniupnpd/Makefile.linux
	miniupnpd/natpmp.c
This commit is contained in:
Thomas Bernard 2014-03-13 14:19:44 +01:00
commit 06764123fb
67 changed files with 1900 additions and 683 deletions

4
README
View File

@ -7,7 +7,7 @@ Freecode : http://freecode.com/projects/miniupnp
miniupnpc/ : MiniUPnP client - an UPnP IGD control point
miniupnpd/ : MiniUPnP daemon - an implementation of a UPnP IGD
+ NAT-PMP gateway
+ NAT-PMP / PCP gateway
minissdpd/ : SSDP managing daemon. Designed to work with miniupnpc, miniupnpd,
minidlna, etc.
@ -43,4 +43,6 @@ Thanks to :
* David Kerr
* Jardel Weyrich
* Leah X. Schmidt
* Peter Tatrai
* Leo Moll
* Daniel Becker

View File

@ -2,4 +2,5 @@
minissdpd
testcodelength
testminissdpd
listifaces
Makefile.bak

View File

@ -1,4 +1,8 @@
$Id: Changelog.txt,v 1.32 2013/08/19 16:40:55 nanard Exp $
$Id: Changelog.txt,v 1.33 2014/02/03 15:45:07 nanard Exp $
2014/02/03:
silently ignore EAGAIN, EWOULDBLOCK, EINTR of recv calls
Discover devices on the network at startup
2013/08/19:
Translate README in english

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.17 2012/05/02 10:26:50 nanard Exp $
# $Id: Makefile,v 1.18 2014/02/03 14:32:14 nanard Exp $
# MiniUPnP project
# author: Thomas Bernard
# website: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
@ -59,6 +59,8 @@ testminissdpd: $(TESTMINISSDPDOBJS)
testcodelength: testcodelength.o
listifaces: listifaces.o upnputils.o
depend:
makedepend -f$(MAKEFILE_LIST) -Y \
$(ALLOBJS:.o=.c) 2>/dev/null

View File

@ -1,4 +1,7 @@
/* $Id: listifaces.c,v 1.4 2007/09/23 16:59:02 nanard Exp $ */
/* $Id: listifaces.c,v 1.6 2014/02/03 14:32:14 nanard Exp $ */
/* (c) 2006-2014 Thomas BERNARD
* http://miniupnp.free.fr/ http://miniupnp.tuxfamily.org/
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
@ -8,7 +11,9 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "upnputils.h"
/* hexdump */
void printhex(const unsigned char * p, int n)
{
int i;
@ -27,19 +32,27 @@ void printhex(const unsigned char * p, int n)
}
}
void listifaces()
/* List network interfaces */
void listifaces(void)
{
struct ifconf ifc;
char * buf = 0;
int buflen = sizeof(struct ifreq)*20;
/*[sizeof(struct ifreq)*8];*/
char * buf = NULL;
int buflen;
int s, i;
int j;
char saddr[256/*INET_ADDRSTRLEN*/];
#ifdef __linux__
buflen = sizeof(struct ifreq)*10;
#else
buflen = 0;
#endif
/*s = socket(PF_INET, SOCK_DGRAM, 0);*/
s = socket(AF_INET, SOCK_DGRAM, 0);
do {
#ifdef __linux__
buflen += buflen;
#endif
if(buflen > 0)
buf = realloc(buf, buflen);
ifc.ifc_len = buflen;
ifc.ifc_buf = (caddr_t)buf;
@ -50,22 +63,39 @@ void listifaces()
free(buf);
return;
}
printf("%d - %d - %d\n", buflen, ifc.ifc_len, (int)sizeof(struct ifreq));
printf(" %d\n", IFNAMSIZ);
printf(" %d %d\n", (int)sizeof(struct sockaddr), (int)sizeof(struct sockaddr_in) );
} while(buflen == ifc.ifc_len);
printf("buffer length=%d - buffer used=%d - sizeof(struct ifreq)=%d\n",
buflen, ifc.ifc_len, (int)sizeof(struct ifreq));
printf("IFNAMSIZ=%d ", IFNAMSIZ);
printf("sizeof(struct sockaddr)=%d sizeof(struct sockaddr_in)=%d\n",
(int)sizeof(struct sockaddr), (int)sizeof(struct sockaddr_in) );
#ifndef __linux__
if(buflen == 0)
buflen = ifc.ifc_len;
else
break;
} while(1);
#else
} while(buflen <= ifc.ifc_len);
#endif
printhex((const unsigned char *)ifc.ifc_buf, ifc.ifc_len);
j = 0;
for(i=0; i<ifc.ifc_len; /*i += sizeof(struct ifreq)*/)
printf("off index fam name address\n");
for(i = 0, j = 0; i<ifc.ifc_len; j++)
{
//const struct ifreq * ifrp = &(ifc.ifc_req[j]);
/*const struct ifreq * ifrp = &(ifc.ifc_req[j]);*/
const struct ifreq * ifrp = (const struct ifreq *)(buf + i);
i += sizeof(ifrp->ifr_name) + 16;//ifrp->ifr_addr.sa_len;
/*inet_ntop(AF_INET, &(((struct sockaddr_in *)&(ifrp->ifr_addr))->sin_addr), saddr, sizeof(saddr));*/
saddr[0] = '\0';
inet_ntop(ifrp->ifr_addr.sa_family, &(ifrp->ifr_addr.sa_data[2]), saddr, sizeof(saddr));
printf("%2d %d %d %s %s\n", j, ifrp->ifr_addr.sa_family, -1/*ifrp->ifr_addr.sa_len*/, ifrp->ifr_name, saddr);
j++;
/* inet_ntop(ifrp->ifr_addr.sa_family, &(ifrp->ifr_addr.sa_data[2]), saddr, sizeof(saddr)); */
sockaddr_to_string(&ifrp->ifr_addr, saddr, sizeof(saddr));
printf("0x%03x %2d %2d %-16s %s\n", i, j, ifrp->ifr_addr.sa_family, ifrp->ifr_name, saddr);
/*ifrp->ifr_addr.sa_len is only available on BSD */
#ifdef __linux__
i += sizeof(struct ifreq);
#else
if(ifrp->ifr_addr.sa_len == 0)
break;
i += IFNAMSIZ + ifrp->ifr_addr.sa_len;
#endif
}
free(buf);
close(s);
@ -73,6 +103,8 @@ void listifaces()
int main(int argc, char * * argv)
{
(void)argc;
(void)argv;
listifaces();
return 0;
}

View File

@ -1,6 +1,6 @@
/* $Id: minissdpd.c,v 1.35 2012/05/21 17:13:11 nanard Exp $ */
/* $Id: minissdpd.c,v 1.37 2014/02/28 18:39:11 nanard Exp $ */
/* MiniUPnP project
* (c) 2007-2012 Thomas Bernard
* (c) 2007-2014 Thomas Bernard
* website : 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 */
@ -224,6 +224,7 @@ SendSSDPMSEARCHResponse(int s, const struct sockaddr * sockname,
n = sendto(s, buf, l, 0,
sockname, sockname_len );
if(n < 0) {
/* XXX handle EINTR, EAGAIN, EWOULDBLOCK */
syslog(LOG_ERR, "sendto(udp): %m");
}
}
@ -282,8 +283,10 @@ processMSEARCH(int s, const char * st, int st_len,
}
} else {
/* find matching services */
/* remove version at the end of the ST string */
if(st[st_len-2]==':' && isdigit(st[st_len-1]))
st_len -= 2;
/* answer for each matching service */
for(serv = servicelisthead.lh_first;
serv;
serv = serv->entries.le_next) {
@ -338,6 +341,7 @@ ParseSSDPPacket(int s, const char * p, ssize_t n,
unsigned int lifetime = 180; /* 3 minutes by default */
const char * st = NULL;
int st_len = 0;
memset(headers, 0, sizeof(headers));
for(methodlen = 0;
methodlen < n && (isalpha(p[methodlen]) || p[methodlen]=='-');
@ -346,6 +350,12 @@ ParseSSDPPacket(int s, const char * p, ssize_t n,
method = METHOD_MSEARCH;
else if(methodlen==6 && 0==memcmp(p, "NOTIFY", 6))
method = METHOD_NOTIFY;
else if(methodlen==4 && 0==memcmp(p, "HTTP", 4)) {
/* answer to a M-SEARCH => process it as a NOTIFY
* with NTS: ssdp:alive */
method = METHOD_NOTIFY;
nts = NTS_SSDP_ALIVE;
}
linestart = p;
while(linestart < p + n - 2) {
/* start parsing the line : detect line end */
@ -435,6 +445,8 @@ ParseSSDPPacket(int s, const char * p, ssize_t n,
} else if(l==2 && 0==strncasecmp(linestart, "st", 2)) {
st = valuestart;
st_len = m;
if(method == METHOD_NOTIFY)
i = HEADER_NT; /* it was a M-SEARCH response */
}
if(i>=0) {
headers[i].p = valuestart;
@ -559,16 +571,16 @@ void processRequest(struct reqelem * req)
syslog(LOG_WARNING, "bad request (length encoding)");
goto error;
}
if(l == 0) {
if(l == 0 && type != 3) {
syslog(LOG_WARNING, "bad request (length=0)");
goto error;
}
syslog(LOG_INFO, "(s=%d) request type=%d str='%.*s'",
req->socket, type, l, p);
switch(type) {
case 1:
case 2:
case 3:
case 1: /* request by type */
case 2: /* request by USN (unique id) */
case 3: /* everything */
while(d && (nrep < 255)) {
if(d->t < t) {
syslog(LOG_INFO, "outdated device");
@ -633,12 +645,14 @@ void processRequest(struct reqelem * req)
}
}
rbuf[0] = nrep;
syslog(LOG_DEBUG, "(s=%d) response : %d device%s",
req->socket, nrep, (nrep > 1) ? "s" : "");
if(write(req->socket, rbuf, rp - rbuf) < 0) {
syslog(LOG_ERR, "(s=%d) write: %m", req->socket);
goto error;
}
break;
case 4:
case 4: /* submit service */
newserv = malloc(sizeof(struct service));
if(!newserv) {
syslog(LOG_ERR, "cannot allocate memory");
@ -779,6 +793,60 @@ sigterm(int sig)
/*errno = save_errno;*/
}
#define PORT 1900
#define XSTR(s) STR(s)
#define STR(s) #s
#define UPNP_MCAST_ADDR "239.255.255.250"
/* for IPv6 */
#define UPNP_MCAST_LL_ADDR "FF02::C" /* link-local */
#define UPNP_MCAST_SL_ADDR "FF05::C" /* site-local */
/* send the M-SEARCH request for all devices */
void ssdpDiscoverAll(int s, int ipv6)
{
static const char MSearchMsgFmt[] =
"M-SEARCH * HTTP/1.1\r\n"
"HOST: %s:" XSTR(PORT) "\r\n"
"ST: ssdp:all\r\n"
"MAN: \"ssdp:discover\"\r\n"
"MX: %u\r\n"
"\r\n";
char bufr[512];
int n;
int mx = 3;
int linklocal = 1;
struct sockaddr_storage sockudp_w;
{
n = snprintf(bufr, sizeof(bufr),
MSearchMsgFmt,
ipv6 ?
(linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]")
: UPNP_MCAST_ADDR, mx);
memset(&sockudp_w, 0, sizeof(struct sockaddr_storage));
if(ipv6) {
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
p->sin6_family = AF_INET6;
p->sin6_port = htons(PORT);
inet_pton(AF_INET6,
linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
&(p->sin6_addr));
} else {
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
p->sin_family = AF_INET;
p->sin_port = htons(PORT);
p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
}
n = sendto(s, bufr, n, 0, (const struct sockaddr *)&sockudp_w,
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
if (n < 0) {
/* XXX : EINTR EWOULDBLOCK EAGAIN */
syslog(LOG_ERR, "sendto: %m");
}
}
}
/* main(): program entry point */
int main(int argc, char * * argv)
{
@ -957,6 +1025,11 @@ int main(int argc, char * * argv)
writepidfile(pidfilename, pid);
/* send M-SEARCH ssdp:all Requests */
ssdpDiscoverAll(s_ssdp, 0);
if(s_ssdp6 >= 0)
ssdpDiscoverAll(s_ssdp6, 1);
/* Main loop */
while(!quitting)
{
@ -997,6 +1070,9 @@ int main(int argc, char * * argv)
(struct sockaddr *)&sendername6, &sendername6_len);
if(n<0)
{
/* EAGAIN, EWOULDBLOCK, EINTR : silently ignore (try again next time)
* other errors : log to LOG_ERR */
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
syslog(LOG_ERR, "recvfrom: %m");
}
else
@ -1028,6 +1104,9 @@ int main(int argc, char * * argv)
(struct sockaddr *)&sendername, &sendername_len);
if(n<0)
{
/* EAGAIN, EWOULDBLOCK, EINTR : silently ignore (try again next time)
* other errors : log to LOG_ERR */
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
syslog(LOG_ERR, "recvfrom: %m");
}
else

View File

@ -1,12 +1,13 @@
/* $Id: testminissdpd.c,v 1.7 2012/05/02 10:28:25 nanard Exp $ */
/* $Id: testminissdpd.c,v 1.8 2014/02/28 18:38:21 nanard Exp $ */
/* Project : miniupnp
* website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
* copyright (c) 2005-2007 Thomas Bernard
* copyright (c) 2005-2014 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
@ -21,6 +22,8 @@ void printresponse(const unsigned char * resp, int n)
int i, l;
unsigned int nresp;
const unsigned char * p;
if(n == 0)
return;
for(i=0; i<n; i++)
printf("%02x ", resp[i]);
printf("\n");
@ -45,6 +48,23 @@ void printresponse(const unsigned char * resp, int n)
#define SENDCOMMAND(command, size) write(s, command, size); \
printf("Command written type=%u\n", (unsigned)command[0]);
int connect_unix_socket(const char * sockpath)
{
int s;
struct sockaddr_un addr;
s = socket(AF_UNIX, SOCK_STREAM, 0);
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
fprintf(stderr, "connecting to %s\n", addr.sun_path);
perror("connect");
exit(1);
}
printf("Connected.\n");
return s;
}
/* test program for minissdpd */
int
main(int argc, char * * argv)
@ -52,7 +72,9 @@ main(int argc, char * * argv)
char command1[] = "\x01\x00urn:schemas-upnp-org:device:InternetGatewayDevice";
char command2[] = "\x02\x00uuid:fc4ec57e-b051-11db-88f8-0060085db3f6::upnp:rootdevice";
char command3[] = { 0x03, 0x00 };
struct sockaddr_un addr;
char command4[] = "\x04\x00test:test:test";
char bad_command[] = { 0xff, 0xff };
char overflow[] = { 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int s;
int i;
unsigned char buf[2048];
@ -65,30 +87,51 @@ main(int argc, char * * argv)
}
command1[1] = sizeof(command1) - 3;
command2[1] = sizeof(command2) - 3;
s = socket(AF_UNIX, SOCK_STREAM, 0);
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
fprintf(stderr, "connecting to %s\n", addr.sun_path);
perror("connect");
return 1;
}
printf("Connected.\n");
command4[1] = sizeof(command4) - 3;
s = connect_unix_socket(sockpath);
SENDCOMMAND(command1, sizeof(command1) - 1);
n = read(s, buf, sizeof(buf));
printf("Response received %d bytes\n", (int)n);
printresponse(buf, n);
if(n == 0) {
close(s);
s = connect_unix_socket(sockpath);
}
SENDCOMMAND(command2, sizeof(command2) - 1);
n = read(s, buf, sizeof(buf));
printf("Response received %d bytes\n", (int)n);
printresponse(buf, n);
if(n == 0) {
close(s);
s = connect_unix_socket(sockpath);
}
SENDCOMMAND(command3, sizeof(command3));
n = read(s, buf, sizeof(buf));
printf("Response received %d bytes\n", (int)n);
printresponse(buf, n);
if(n == 0) {
close(s);
s = connect_unix_socket(sockpath);
}
SENDCOMMAND(command4, sizeof(command4));
SENDCOMMAND(bad_command, sizeof(bad_command));
n = read(s, buf, sizeof(buf));
printf("Response received %d bytes\n", (int)n);
printresponse(buf, n);
if(n == 0) {
close(s);
s = connect_unix_socket(sockpath);
}
SENDCOMMAND(overflow, sizeof(overflow));
n = read(s, buf, sizeof(buf));
printf("Response received %d bytes\n", (int)n);
printresponse(buf, n);
close(s);
return 0;

View File

@ -1,8 +1,8 @@
cmake_minimum_required (VERSION 2.6)
project (miniupnpc C)
set (MINIUPNPC_VERSION 1.7)
set (MINIUPNPC_API_VERSION 9)
set (MINIUPNPC_VERSION 1.9)
set (MINIUPNPC_API_VERSION 10)
if (NOT CMAKE_BUILD_TYPE)
if (WIN32)

View File

@ -1,6 +1,18 @@
$Id: Changelog.txt,v 1.189 2013/10/07 10:04:55 nanard Exp $
$Id: Changelog.txt,v 1.193 2014/02/05 17:26:45 nanard Exp $
miniUPnP client Changelog.
2014/02/05:
handle EINPROGRESS after connect()
2014/02/03:
minixml now handle XML comments
VERSION 1.9 : released 2014/01/31
2014/01/31:
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
increment API_VERSION to 10
2013/12/09:
--help and -h arguments in upnpc.c

View File

@ -3,7 +3,7 @@
# http://miniupnp.free.fr/
# http://miniupnp.tuxfamily.org/
# https://github.com/miniupnp/miniupnp
# (c) 2005-2013 Thomas Bernard
# (c) 2005-2014 Thomas Bernard
# to install use :
# $ make DESTDIR=/tmp/dummylocation install
# or
@ -55,7 +55,7 @@ ifeq (SunOS, $(OS))
endif
# APIVERSION is used to build SONAME
APIVERSION = 9
APIVERSION = 10
SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \
upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \
@ -175,7 +175,8 @@ validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh
clean:
$(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h
# clean python stuff
$(RM) pythonmodule pythonmodule3 validateminixml validateminiwget
$(RM) pythonmodule pythonmodule3
$(RM) validateminixml validateminiwget validateupnpreplyparse
$(RM) -r build/ dist/
#python setup.py clean
# clean jnaerator stuff

View File

@ -1,7 +1,7 @@
# $Id: Makefile.mingw,v 1.17 2012/12/02 14:12:45 nanard Exp $
# $Id: Makefile.mingw,v 1.18 2014/01/17 09:04:01 nanard Exp $
# Miniupnp project.
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
# (c) 2005-2011 Thomas Bernard
# (c) 2005-2014 Thomas Bernard
# This Makefile is made for MinGW
#
CC = gcc
@ -57,11 +57,12 @@ upnpc.o:
$(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $<
$(CC) $(CFLAGS) -c -o dll/$@ $<
# --enable-stdcall-fixup
upnpc-static: upnpc.o libminiupnpc.a
$(CC) -enable-stdcall-fixup -o $@ $^ $(LDLIBS)
$(CC) -o $@ $^ $(LDLIBS)
upnpc-shared: dll/upnpc.o miniupnpc.lib
$(CC) -enable-stdcall-fixup -o $@ $^ $(LDLIBS)
$(CC) -o $@ $^ $(LDLIBS)
wingenminiupnpcstrings: wingenminiupnpcstrings.o

View File

@ -1 +1 @@
1.8
1.9

View File

@ -1,7 +1,17 @@
$Id: apiversions.txt,v 1.2 2013/03/29 14:45:09 nanard Exp $
$Id: apiversions.txt,v 1.3 2014/01/31 13:14:32 nanard Exp $
Differences in API between miniUPnPc versions
====================== miniUPnPc version 1.9 ======================
API version 10
upnpcommands.h:
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
miniupnpc.h:
updated macros :
#define MINIUPNPC_VERSION "1.9"
#define MINIUPNPC_API_VERSION 10
====================== miniUPnPc version 1.8 ======================
API version 9

View File

@ -1,7 +1,7 @@
/* $Id: connecthostport.c,v 1.11 2013/08/01 21:21:25 nanard Exp $ */
/* $Id: connecthostport.c,v 1.12 2014/02/05 17:26:46 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2010-2013 Thomas Bernard
* Copyright (c) 2010-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@ -109,7 +109,10 @@ int connecthostport(const char * host, unsigned short port,
dest.sin_port = htons(port);
n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
#ifdef MINIUPNPC_IGNORE_EINTR
while(n < 0 && errno == EINTR)
/* EINTR The system call was interrupted by a signal that was caught
* EINPROGRESS The socket is nonblocking and the connection cannot
* be completed immediately. */
while(n < 0 && (errno == EINTR || errno = EINPROGRESS))
{
socklen_t len;
fd_set wset;
@ -203,7 +206,10 @@ int connecthostport(const char * host, unsigned short port,
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
n = connect(s, p->ai_addr, p->ai_addrlen);
#ifdef MINIUPNPC_IGNORE_EINTR
while(n < 0 && errno == EINTR)
/* EINTR The system call was interrupted by a signal that was caught
* EINPROGRESS The socket is nonblocking and the connection cannot
* be completed immediately. */
while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
{
socklen_t len;
fd_set wset;

View File

@ -72,7 +72,7 @@ public class JavaBridgeTest {
System.out.println("AddPortMapping() failed with code " + ret);
ret = miniupnpc.UPNP_GetSpecificPortMappingEntry(
urls.controlURL.getString(0), new String(data.first.servicetype),
args[0], args[1], intClient, intPort,
args[0], args[1], null, intClient, intPort,
desc, enabled, leaseDuration);
if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS)
System.out.println("GetSpecificPortMappingEntry() failed with code " + ret);

View File

@ -1,8 +1,8 @@
/* $Id: miniupnpc.c,v 1.113 2013/10/07 10:04:56 nanard Exp $ */
/* $Id: miniupnpc.c,v 1.116 2014/01/31 14:09:03 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
* copyright (c) 2005-2013 Thomas Bernard
* copyright (c) 2005-2014 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#define __EXTENSIONS__ 1
@ -545,7 +545,8 @@ upnpDiscover(int delay, const char * multicastif,
}
}
/* Avant d'envoyer le paquet on bind pour recevoir la reponse */
/* Before sending the packed, we first "bind" in order to be able
* to receive the response */
if (bind(sudp, (const struct sockaddr *)&sockudp_r,
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0)
{
@ -560,6 +561,10 @@ upnpDiscover(int delay, const char * multicastif,
*error = UPNPDISCOVER_SUCCESS;
/* Calculating maximum response time in seconds */
mx = ((unsigned int)delay) / 1000u;
if(mx == 0) {
mx = 1;
delay = 1000;
}
/* receiving SSDP response packet */
for(n = 0; deviceList[deviceIndex]; deviceIndex++)
{

View File

@ -1,5 +1,6 @@
LIBRARY
; miniupnpc library
miniupnpc
EXPORTS
; miniupnpc

View File

@ -1,4 +1,4 @@
/* $Id: miniupnpc.h,v 1.32 2013/02/06 14:44:42 nanard Exp $ */
/* $Id: miniupnpc.h,v 1.34 2014/01/31 13:18:25 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
@ -18,8 +18,8 @@
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
#define MINIUPNPC_VERSION "1.8"
#define MINIUPNPC_API_VERSION 9
#define MINIUPNPC_VERSION "1.9"
#define MINIUPNPC_API_VERSION 10
#ifdef __cplusplus
extern "C" {

View File

@ -1,8 +1,8 @@
/* $Id: miniupnpcmodule.c,v 1.19 2012/01/21 13:30:32 nanard Exp $*/
/* $Id: miniupnpcmodule.c,v 1.22 2014/01/31 13:18:25 nanard Exp $*/
/* Project : miniupnp
* Author : Thomas BERNARD
* website : http://miniupnp.tuxfamily.org/
* copyright (c) 2007-2012 Thomas Bernard
* copyright (c) 2007-2014 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#include <Python.h>
@ -310,7 +310,7 @@ Py_END_ALLOW_THREADS
}
}
/* GetSpecificPortMapping(ePort, proto)
/* GetSpecificPortMapping(ePort, proto, remoteHost='')
* proto = 'UDP' or 'TCP' */
static PyObject *
UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
@ -318,13 +318,14 @@ UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
char extPort[6];
unsigned short ePort;
const char * proto;
const char * remoteHost = "";
char intClient[40];
char intPort[6];
unsigned short iPort;
char desc[80];
char enabled[4];
char leaseDuration[16];
if(!PyArg_ParseTuple(args, "Hs", &ePort, &proto))
if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
return NULL;
extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0';
desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0';
@ -332,7 +333,7 @@ Py_BEGIN_ALLOW_THREADS
sprintf(extPort, "%hu", ePort);
UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
self->data.first.servicetype,
extPort, proto,
extPort, proto, remoteHost,
intClient, intPort,
desc, enabled, leaseDuration);
Py_END_ALLOW_THREADS

View File

@ -1,8 +1,8 @@
/* $Id: miniwget.c,v 1.60 2013/10/07 10:03:16 nanard Exp $ */
/* $Id: miniwget.c,v 1.61 2014/02/05 17:27:48 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2013 Thomas Bernard
* Copyright (c) 2005-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@ -39,9 +39,6 @@
#include <net/if.h>
#include <netdb.h>
#define closesocket close
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
#endif /* #else _WIN32 */
#if defined(__sun) || defined(sun)
#define MIN(x,y) (((x)<(y))?(x):(y))

View File

@ -1,10 +1,10 @@
/* $Id: minixml.c,v 1.9 2011/02/07 13:44:57 nanard Exp $ */
/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */
/* minixml.c : the minimum size a xml parser can be ! */
/* Project : miniupnp
* webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
Copyright (c) 2005-2011, Thomas BERNARD
Copyright (c) 2005-2014, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -113,7 +113,20 @@ static void parseelt(struct xmlparser * p)
const char * elementname;
while(p->xml < (p->xmlend - 1))
{
if((p->xml)[0]=='<' && (p->xml)[1]!='?')
if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "<!--", 4)))
{
p->xml += 3;
/* ignore comments */
do
{
p->xml++;
if ((p->xml + 3) >= p->xmlend)
return;
}
while(memcmp(p->xml, "-->", 3) != 0);
p->xml += 3;
}
else if((p->xml)[0]=='<' && (p->xml)[1]!='?')
{
i = 0; elementname = ++p->xml;
while( !IS_WHITE_SPACE(*p->xml)

View File

@ -0,0 +1,3 @@
NewProtocol=UDP
NewExternalPort=12345
NewRemoteHost=

View File

@ -0,0 +1,3 @@
<?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:GetSpecificPortMappingEntry xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost></NewRemoteHost><NewExternalPort>12345</NewExternalPort><NewProtocol>UDP</NewProtocol></u:GetSpecificPortMappingEntry></s:Body></s:Envelope>

View File

@ -0,0 +1,5 @@
NewInternalPort=12345
NewInternalClient=192.168.10.110
NewEnabled=1
NewPortMappingDescription=libminiupnpc
NewLeaseDuration=0

View File

@ -0,0 +1,2 @@
<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetSpecificPortMappingEntryResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewInternalPort>12345</NewInternalPort><NewInternalClient>192.168.10.110</NewInternalClient><NewEnabled>1</NewEnabled><NewPortMappingDescription>libminiupnpc</NewPortMappingDescription><NewLeaseDuration>0</NewLeaseDuration></u:GetSpecificPortMappingEntryResponse></s:Body></s:Envelope>

View File

@ -1,7 +1,7 @@
/* $Id: testupnpreplyparse.c,v 1.3 2013/05/14 20:37:36 nanard Exp $ */
/* $Id: testupnpreplyparse.c,v 1.4 2014/01/27 11:45:19 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdio.h>
@ -74,7 +74,7 @@ int main(int argc, char * * argv)
fclose(f);
f = NULL;
buffer[l] = '\0';
if(argc >= 2)
if(argc > 2)
{
f = fopen(argv[2], "r");
if(!f)

View File

@ -1,7 +1,7 @@
/* $Id: upnpc.c,v 1.99 2013/02/06 12:56:41 nanard Exp $ */
/* $Id: upnpc.c,v 1.102 2014/02/05 17:27:14 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2013 Thomas Bernard
* Copyright (c) 2005-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@ -266,7 +266,7 @@ static void SetRedirectAndTest(struct UPNPUrls * urls,
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
data->first.servicetype,
eport, proto,
eport, proto, NULL/*remoteHost*/,
intClient, intPort, NULL/*desc*/,
NULL/*enabled*/, duration);
if(r!=UPNPCOMMAND_SUCCESS)
@ -500,7 +500,7 @@ int main(int argc, char ** argv)
return -1;
}
#endif
printf("upnpc : miniupnpc library test client. (c) 2005-2013 Thomas Bernard\n");
printf("upnpc : miniupnpc library test client. (c) 2005-2014 Thomas Bernard\n");
printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
"for more information.\n");
/* command line processing */

View File

@ -1,4 +1,4 @@
/* $Id: upnpcommands.c,v 1.41 2013/12/09 08:18:23 nanard Exp $ */
/* $Id: upnpcommands.c,v 1.42 2014/01/31 13:18:25 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
@ -579,6 +579,7 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * extPort,
const char * proto,
const char * remoteHost,
char * intClient,
char * intPort,
char * desc,
@ -597,7 +598,7 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
GetPortMappingArgs[0].elt = "NewRemoteHost";
/* TODO : add remote host ? */
GetPortMappingArgs[0].val = remoteHost;
GetPortMappingArgs[1].elt = "NewExternalPort";
GetPortMappingArgs[1].val = extPort;
GetPortMappingArgs[2].elt = "NewProtocol";

View File

@ -1,7 +1,7 @@
/* $Id: upnpcommands.h,v 1.23 2011/04/11 09:14:00 nanard Exp $ */
/* $Id: upnpcommands.h,v 1.27 2014/02/17 15:38:26 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* Copyright (c) 2005-2014 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef UPNPCOMMANDS_H_INCLUDED
@ -100,6 +100,8 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
* errorCode errorDescription (short) - Description (long)
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization and
* the sender was not authorized.
* 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
* wild-carded
* 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
@ -112,7 +114,13 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
* 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
* and cannot be a specific IP address or DNS name
* 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
* cannot be a specific port value */
* cannot be a specific port value
* 728 NoPortMapsAvailable - There are not enough free ports available to
* complete port mapping.
* 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed
* due to conflict with other mechanisms.
* 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded
*/
LIBSPEC int
UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
@ -132,6 +140,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
*
* List of possible UPnP errors for DeletePortMapping :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 714 NoSuchEntryInArray - The specified value does not exist in the array */
LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
@ -150,6 +160,7 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
* params :
* in extPort
* in proto
* in remoteHost
* out intClient (16 bytes)
* out intPort (6 bytes)
* out desc (80 bytes)
@ -158,12 +169,21 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
*
* return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
* or a UPnP Error Code. */
* or a UPnP Error Code.
*
* List of possible UPnP errors for _GetSpecificPortMappingEntry :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 714 NoSuchEntryInArray - The specified value does not exist in the array.
*/
LIBSPEC int
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * extPort,
const char * proto,
const char * remoteHost,
char * intClient,
char * intPort,
char * desc,
@ -188,6 +208,8 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
*
* Possible UPNP Error codes :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 606 Action not authorized - The action requested REQUIRES authorization
* and the sender was not authorized.
* 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
*/
LIBSPEC int

View File

@ -9,3 +9,7 @@ testgetifstats
testupnpdescgen
testupnppermissions
testgetroute
testasyncsendto
netfilter/testiptcrdr
netfilter/testiptcrdr_dscp
netfilter/testiptcrdr_peer

View File

@ -1,7 +1,53 @@
$Id: Changelog.txt,v 1.345 2013/06/13 13:21:28 nanard Exp $
$Id: Changelog.txt,v 1.363 2014/03/13 10:53:40 nanard Exp $
2014/03/13:
fix getifaddr_in6() (used for PCP)
implement permissions with PCP Map
fix upnp_event_notify_connect() when ENABLE_IPV6 is set
2014/03/10:
Enable PCP by default.
Work in IPv6 on system where PF_INET6 are restricted to IPv6 only
change ipv6_enabled/ipv6fc_inbound_pinhole_allowed/ipv6fc_firewall_enabled
global vars to flags in runtime_flags
2014/03/09:
IPv6 support in testgetifaddr
2014/03/07:
NAT-PMP search an allowed eport instead of returning an error
if the original eport is not allowed.
2014/03/06:
Fix add_filter_rule2() for pf.
2014/02/28:
log message when shutting down
natpmp : avoid hang when all external ports in use
2014/02/25:
add implementation of scheduled sendto (asyncsendto) in order
to retry failed sendto() calls or schedule sending of packets
2014/02/24:
Defaulting to SSDP_RESPOND_SAME_VERSION
2014/02/11:
Fix PCP Map renewal
2014/02/06:
possibility to disable ipv6 at runtime
2014/02/03:
PCP : Add support for ANNOUNCE requests
minixml now handle XML comments
2013/12/16:
Attempt to compile with OS X/pf
2013/12/13:
Make all manufacturer info configurable thanks to Leo Moll
Merge PCP support (see https://github.com/miniupnp/miniupnp)
2013/06/13:
Have 3 UUID for the 3 devices (IGD, WAN Device, WAN Connection Device)

View File

@ -1,5 +1,5 @@
MiniUPnP project.
(c) 2006-2013 Thomas Bernard
(c) 2006-2014 Thomas Bernard
Homepage : http://miniupnp.free.fr/
Mirror: http://miniupnp.tuxfamily.org/
github: https://github.com/miniupnp/miniupnp
@ -17,7 +17,9 @@ To Build and Install :
Alternatively to editing config.h, options can be passed to genconfig.sh
For more details :
> ./genconfig.sh -h
- add "rdr-anchor miniupnpd" and "anchor miniupnpd" lines to /etc/pf.conf
- add "rdr-anchor miniupnpd" or/and "anchor miniupnpd" lines to /etc/pf.conf
(Since OpenBSD 4.7, rdr-anchor lines are no longer used and should be
removed, leaving only the anchor lines).
- some FreeBSD users reported that it is also necessary for them
to explicitly allow udp traffic on 239.0.0.0/8 by adding the two following
lines to /etc/pf.conf :
@ -26,7 +28,7 @@ To Build and Install :
- dont forget to " pfctl -f /etc/pf.conf "
- you can check your modifications are taken into accout with
"pfctl -s nat" and "pfctl -s rule". Look for the "rdr-anchor miniupnpd"
and "anchor miniupnpd" lines.
(if applicable) and/or "anchor miniupnpd" lines.
- install as root using :
# make install
or
@ -53,7 +55,17 @@ http://blogs.sun.com/avalon/category/IPFilter
- To enable non standard compilation options,
> ./genconfig.sh -h
Or edit config.h after it has been generated by genconfig.sh
- use 'bsdmake' or 'make -f Makefile.macosx' to build
- use 'bsdmake' (if available) or 'make -f Makefile.macosx' to build
============================== Mac OS X/pf ================================
Starting with Mac OS X 10.7 Lion, pf replaced ipfw as the OS X firewall.
also bsdmake is not available anymore.
Make sure you have installed the Xcode commande line tools (from the
Xcode Preferences menu or using 'xcode-select --install' command)
You'll need to download xnu sources : https://github.com/opensource-apple/xnu
> INCLUDES="-I.../xnu/bsd -I.../xnu/libkern" make -f Makefile.macosx
============================ Linux/netfilter ==============================
To Build and install :
@ -108,11 +120,11 @@ also available through command line switches.
Miniupnpd supports some kind of security check for allowing or disallowing
redirection to be made. The UPnP permission rules are read from the
miniupnpd.conf configuration file.
When a new redirection is asked, permission rules are evaluated in top-down
order and the first permission rule matched gives the answer : redirection
allowed or denied. If no rule is matching, the redirection is allowed, so
it is a good practice to have a "catch all" deny permission rule at the end
of your mermission ruleset.
When a new redirection is requested, permission rules are evaluated in
top-down order and the first permission rule matched gives the response :
redirection allowed or denied. If no rule is matching, the redirection is
allowed, so it is a good practice to have a "catch all" deny permission
rule at the end of your permission ruleset.
Sample permission ruleset :
allow 4662-4672 192.168.1.34/32 4662-4672
deny 0-65535 192.168.1.34/32 0-65535
@ -137,8 +149,8 @@ More simple, use the genuuid makefile target :
> make genuuid
or
> make -f Makefile.linux genuuid
This target is needed by the "install" target, so it should be done
automatically.
This target is needed by the "install" target, so it is done automatically
during install.
To stop the daemon use :
# kill `cat /var/run/miniupnpd.pid`

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.73 2013/02/06 13:11:45 nanard Exp $
# $Id: Makefile,v 1.76 2014/03/10 10:26:15 nanard Exp $
# MiniUPnP project
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
# Author: Thomas Bernard
@ -78,9 +78,9 @@ CFLAGS += -m64 -mcmodel=medlow
STDOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \
options.o upnppermissions.o minissdp.o natpmp.o \
options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \
upnpevents.o upnputils.o getconnstatus.o \
upnppinhole.o
upnppinhole.o asyncsendto.o
BSDOBJS = bsd/getifstats.o bsd/ifacewatcher.o bsd/getroute.o
SUNOSOBJS = solaris/getifstats.o bsd/ifacewatcher.o bsd/getroute.o
MACOBJS = mac/getifstats.o bsd/ifacewatcher.o bsd/getroute.o
@ -116,10 +116,11 @@ TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o
TESTUPNPPERMISSIONSOBJS = testupnppermissions.o upnppermissions.o
TESTGETIFADDROBJS = testgetifaddr.o getifaddr.o
MINIUPNPDCTLOBJS = miniupnpdctl.o
TESTASYNCSENDTOOBJS = testasyncsendto.o asyncsendto.o upnputils.o bsd/getroute.o
EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \
testupnppermissions miniupnpdctl \
testgetifaddr testgetroute
testgetifaddr testgetroute testasyncsendto
.if $(OSNAME) == "Darwin"
LIBS =
.else
@ -142,13 +143,13 @@ clean:
$(RM) $(STDOBJS) $(BSDOBJS) $(SUNOSOBJS) $(MACOBJS) $(EXECUTABLES) \
testupnpdescgen.o \
$(MISCOBJS) config.h testgetifstats.o testupnppermissions.o \
miniupnpdctl.o testgetifaddr.o testgetroute.o \
miniupnpdctl.o testgetifaddr.o testgetroute.o testasyncsendto.o \
$(PFOBJS) $(IPFOBJS) $(IPFWOBJS)
install: miniupnpd genuuid
$(STRIP) miniupnpd
$(INSTALL) -d $(DESTDIR)$(INSTALLBINDIR)
$(INSTALL) -m 555 miniupnpd $(DESTDIR)$(INSTALLBINDIR)
$(INSTALL) -m 755 miniupnpd $(DESTDIR)$(INSTALLBINDIR)
$(INSTALL) -d $(DESTDIR)$(INSTALLETCDIR)
$(INSTALL) -b miniupnpd.conf $(DESTDIR)$(INSTALLETCDIR)
# TODO : install man page correctly
@ -199,6 +200,9 @@ testupnppermissions: config.h $(TESTUPNPPERMISSIONSOBJS)
testgetroute: config.h $(TESTGETROUTEOBJS)
$(CC) $(CFLAGS) -o $@ $(TESTGETROUTEOBJS)
testasyncsendto: config.h $(TESTASYNCSENDTOOBJS)
$(CC) $(CFLAGS) -o $@ $(TESTASYNCSENDTOOBJS)
# gmake :
# $(CC) $(CFLAGS) -o $@ $^
# BSDmake :

View File

@ -1,6 +1,6 @@
# $Id: Makefile.linux,v 1.78 2013/05/03 09:30:33 nanard Exp $
# $Id: Makefile.linux,v 1.81 2014/01/27 10:06:58 nanard Exp $
# MiniUPnP project
# (c) 2006-2013 Thomas Bernard
# (c) 2006-2014 Thomas Bernard
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
# Author : Thomas Bernard
# for use with GNU Make
@ -45,9 +45,9 @@ MANINSTALLDIR = $(INSTALLPREFIX)/share/man/man8
BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
upnpreplyparse.o minixml.o portinuse.o \
upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \
options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o\
options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \
upnpevents.o upnputils.o getconnstatus.o \
upnppinhole.o pcplearndscp.o
upnppinhole.o pcplearndscp.o asyncsendto.o
LNXOBJS = linux/getifstats.o linux/ifacewatcher.o linux/getroute.o
NETFILTEROBJS = netfilter/iptcrdr.o netfilter/iptpinhole.o netfilter/nfct_get.o
@ -150,7 +150,7 @@ TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o
EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \
testupnppermissions miniupnpdctl testgetifaddr \
testgetroute
testgetroute testasyncsendto
.PHONY: all clean install depend genuuid
@ -161,7 +161,7 @@ clean:
$(RM) $(EXECUTABLES)
$(RM) testupnpdescgen.o testgetifstats.o
$(RM) testupnppermissions.o testgetifaddr.o
$(RM) testgetroute.o
$(RM) testgetroute.o testasyncsendto.o
$(RM) miniupnpdctl.o
install: miniupnpd miniupnpd.8 miniupnpd.conf genuuid \
@ -205,6 +205,9 @@ testgetifaddr: testgetifaddr.o getifaddr.o
testgetroute: testgetroute.o linux/getroute.o upnputils.o -lnfnetlink
testasyncsendto: testasyncsendto.o asyncsendto.o upnputils.o \
linux/getroute.o -lnfnetlink
miniupnpdctl: miniupnpdctl.o
config.h: genconfig.sh VERSION
@ -214,15 +217,15 @@ depend: config.h
makedepend -f$(MAKEFILE_LIST) -Y \
$(ALLOBJS:.o=.c) $(TESTUPNPDESCGENOBJS:.o=.c) \
testgetifstats.c testupnppermissions.c testgetifaddr.c \
testgetroute.c miniupnpdctl.c 2>/dev/null
testgetroute.c testasyncsendto.c miniupnpdctl.c 2>/dev/null
# DO NOT DELETE
miniupnpd.o: config.h macros.h upnpglobalvars.h upnppermissions.h
miniupnpd.o: miniupnpdtypes.h upnphttp.h upnpdescgen.h miniupnpdpath.h
miniupnpd.o: getifaddr.h upnpsoap.h options.h minissdp.h upnpredirect.h
miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h natpmp.h commonrdr.h
miniupnpd.o: upnputils.h ifacewatcher.h
miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h asyncsendto.h natpmp.h
miniupnpd.o: pcpserver.h commonrdr.h upnputils.h ifacewatcher.h
upnphttp.o: config.h upnphttp.h upnpdescgen.h miniupnpdpath.h upnpsoap.h
upnphttp.o: upnpevents.h upnputils.h
upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h
@ -249,21 +252,25 @@ options.o: miniupnpdtypes.h
upnppermissions.o: config.h upnppermissions.h
minissdp.o: config.h upnpdescstrings.h miniupnpdpath.h upnphttp.h
minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h
minissdp.o: upnputils.h getroute.h codelength.h
minissdp.o: upnputils.h getroute.h asyncsendto.h codelength.h
natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h
natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h
natpmp.o: portinuse.h
pcpserver.o: config.h
natpmp.o: portinuse.h asyncsendto.h
pcpserver.o: config.h pcpserver.h macros.h upnpglobalvars.h upnppermissions.h
pcpserver.o: miniupnpdtypes.h pcplearndscp.h upnpredirect.h commonrdr.h
pcpserver.o: getifaddr.h asyncsendto.h pcp_msg_struct.h netfilter/iptcrdr.h
pcpserver.o: commonrdr.h
upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h
upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h
upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h
upnputils.o: miniupnpdtypes.h
upnputils.o: miniupnpdtypes.h getroute.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
asyncsendto.o: asyncsendto.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
@ -275,12 +282,14 @@ 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 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
testgetifstats.o: getifstats.h
testupnppermissions.o: upnppermissions.h config.h
testgetifaddr.o: getifaddr.h
testgetifaddr.o: config.h getifaddr.h
testgetroute.o: getroute.h upnputils.h upnpglobalvars.h upnppermissions.h
testgetroute.o: config.h miniupnpdtypes.h
testasyncsendto.o: miniupnpdtypes.h config.h upnputils.h asyncsendto.h
miniupnpdctl.o: macros.h

View File

@ -3,6 +3,10 @@
# Author: Thomas Bernard
# This Makefile should work for MacOSX
#
# To compile with pf with OS X 10.7+, you need to specify
# path to XNU bsd sources :
# INCLUDES="-I.../xnu/bsd I.../xnu/libkern" make -f Makefile.macosx
#
# To install use :
# $ PREFIX=/dummyinstalldir make -f Makefile.macosx install
# or :
@ -10,26 +14,38 @@
#
CFLAGS = -Wall -O -g3 -DDEBUG
#CFLAGS = -Wall -Os
CC = gcc
#CC = gcc #better use clang !
RM = rm -f
MV = mv
INSTALL = install
STRIP = strip
CFLAGS += -DMACOSX
# OSNAME and FWNAME are used for building OS or FW dependent code.
OSNAME = $(shell uname)
ARCH = $(shell uname -p)
FWNAME = ipfw
# Firewall is ipfw up to OS X 10.6 Snow Leopard
# and pf since OS X 10.7 Lion (Darwin 11.0)
FWNAME = $(shell [ `uname -r | cut -d. -f1` -ge 11 ] && echo "pf" || echo "ipfw" )
STD_OBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \
options.o upnppermissions.o minissdp.o natpmp.o \
upnpevents.o getconnstatus.o upnputils.o
upnpevents.o getconnstatus.o upnputils.o \
asyncsendto.o
MAC_OBJS = mac/getifstats.o bsd/ifacewatcher.o
IPFW_OBJS = ipfw/ipfwrdr.o ipfw/ipfwaux.o
PF_OBJS = pf/obsdrdr.o pf/pfpinhole.o
MISC_OBJS = upnpreplyparse.o minixml.o
ALL_OBJS = $(STD_OBJS) $(MISC_OBJS) $(MAC_OBJS) $(IPFW_OBJS)
ALL_OBJS = $(STD_OBJS) $(MISC_OBJS) $(MAC_OBJS)
ifeq ($(FWNAME), ipfw)
ALL_OBJS += $(IPFW_OBJS)
else
ALL_OBJS += $(PF_OBJS)
CFLAGS += -DPF
endif
TEST_UPNPDESCGEN_OBJS = testupnpdescgen.o upnpdescgen.o
TEST_GETIFSTATS_OBJS = testgetifstats.o mac/getifstats.o
@ -106,5 +122,5 @@ config.h: genconfig.sh
.SUFFIXES: .o .c
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
# $(CC) $(CFLAGS) -c -o $(.TARGET) $(.IMPSRC)

View File

@ -1,5 +1,5 @@
MiniUPnP project
(c) 2006-2012 Thomas Bernard
(c) 2006-2014 Thomas Bernard
webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
github: https://github.com/miniupnp/miniupnp
freecode: http://freecode.com/projects/miniupnp
@ -22,8 +22,11 @@ Support for the NAT Port Mapping Protocol (NAT-PMP) has been
added. See information about NAT-PMP here :
http://miniupnp.free.fr/nat-pmp.html
NAT-PMP is the precursor of Port Control Protocol (PCP).
In 2013, support for PCP has been added too.
Read the INSTALL files for instructions to compile, install and
configure miniupnpd.
configure miniupnpd on your system.
Report bugs to miniupnp@free.fr on the web forum
http://miniupnp.tuxfamily.org/forum/

273
miniupnpd/asyncsendto.c Normal file
View File

@ -0,0 +1,273 @@
/* $Id: $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include "asyncsendto.h"
/* state diagram for a packet :
*
* |
* V
* -> ESCHEDULED -> ESENDNOW -> sent
* ^ |
* | V
* EWAITREADY -> sent
*/
struct scheduled_send {
LIST_ENTRY(scheduled_send) entries;
struct timeval ts;
enum {ESCHEDULED=1, EWAITREADY=2, ESENDNOW=3} state;
int sockfd;
const void * buf;
size_t len;
int flags;
const struct sockaddr *dest_addr;
socklen_t addrlen;
char data[];
};
static LIST_HEAD(listhead, scheduled_send) send_list = { NULL };
/*
* ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
* const struct sockaddr *dest_addr, socklen_t addrlen);
*/
/* delay = milli seconds */
ssize_t
sendto_schedule(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen,
unsigned int delay)
{
enum {ESCHEDULED, EWAITREADY, ESENDNOW} state;
ssize_t n;
struct timeval tv;
struct scheduled_send * elt;
if(delay == 0) {
/* first try to send at once */
n = sendto(sockfd, buf, len, flags, dest_addr, addrlen);
if(n >= 0)
return n;
else if(errno == EAGAIN || errno == EWOULDBLOCK) {
/* use select() on this socket */
state = EWAITREADY;
} else if(errno == EINTR) {
state = ESENDNOW;
} else {
/* uncatched error */
return n;
}
} else {
state = ESCHEDULED;
}
/* schedule */
if(gettimeofday(&tv, 0) < 0) {
return -1;
}
/* allocate enough space for structure + buffers */
elt = malloc(sizeof(struct scheduled_send) + len + addrlen);
if(elt == NULL) {
syslog(LOG_ERR, "malloc failed to allocate %u bytes",
(unsigned)(sizeof(struct scheduled_send) + len + addrlen));
return -1;
}
elt->state = state;
/* time the packet should be sent */
elt->ts.tv_sec = tv.tv_sec + (delay / 1000);
elt->ts.tv_usec = tv.tv_usec + (delay % 1000) * 1000;
if(elt->ts.tv_usec > 1000000) {
elt->ts.tv_sec++;
elt->ts.tv_usec -= 1000000;
}
elt->sockfd = sockfd;
elt->flags = flags;
memcpy(elt->data, dest_addr, addrlen);
elt->dest_addr = (struct sockaddr *)elt->data;
elt->addrlen = addrlen;
memcpy(elt->data + addrlen, buf, len);
elt->buf = (void *)(elt->data + addrlen);
elt->len = len;
/* insert */
LIST_INSERT_HEAD( &send_list, elt, entries);
return 0;
}
/* try to send at once, and queue the packet if needed */
ssize_t
sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
{
return sendto_schedule(sockfd, buf, len, flags, dest_addr, addrlen, 0);
}
/* get_next_scheduled_send() return number of scheduled send in list */
int get_next_scheduled_send(struct timeval * next_send)
{
int n = 0;
struct scheduled_send * elt;
if(next_send == NULL)
return -1;
for(elt = send_list.lh_first; elt != NULL; elt = elt->entries.le_next) {
if(n == 0 || (elt->ts.tv_sec < next_send->tv_sec) ||
(elt->ts.tv_sec == next_send->tv_sec && elt->ts.tv_usec < next_send->tv_usec)) {
next_send->tv_sec = elt->ts.tv_sec;
next_send->tv_usec = elt->ts.tv_usec;
}
n++;
}
return n;
}
/* update writefds for select() call
* return the number of packets to try to send at once */
int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now)
{
int n = 0;
struct scheduled_send * elt;
for(elt = send_list.lh_first; elt != NULL; elt = elt->entries.le_next) {
if(elt->state == EWAITREADY) {
/* last sendto() call returned EAGAIN/EWOULDBLOCK */
FD_SET(elt->sockfd, writefds);
if(elt->sockfd > *max_fd)
*max_fd = elt->sockfd;
n++;
} else if((elt->ts.tv_sec < now->tv_sec) ||
(elt->ts.tv_sec == now->tv_sec && elt->ts.tv_usec <= now->tv_usec)) {
/* we waited long enough, now send ! */
elt->state = ESENDNOW;
n++;
}
}
return n;
}
/* executed sendto() when needed */
int try_sendto(fd_set * writefds)
{
ssize_t n;
struct scheduled_send * elt;
struct scheduled_send * next;
for(elt = send_list.lh_first; elt != NULL; elt = next) {
next = elt->entries.le_next;
if((elt->state == ESENDNOW) ||
(elt->state == EWAITREADY && FD_ISSET(elt->sockfd, writefds))) {
syslog(LOG_DEBUG, "try_sendto(): %d bytes on socket %d",
(int)elt->len, elt->sockfd);
n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags,
elt->dest_addr, elt->addrlen);
if(n < 0) {
if(errno == EINTR) {
/* retry at once */
elt->state = ESENDNOW;
continue;
} else if(errno == EAGAIN || errno == EWOULDBLOCK) {
/* retry once the socket is ready for writing */
elt->state = EWAITREADY;
continue;
}
/* uncatched error */
/* remove from the list */
LIST_REMOVE(elt, entries);
free(elt);
return n;
} else {
/* remove from the list */
LIST_REMOVE(elt, entries);
free(elt);
}
}
}
return 0;
}
/* maximum execution time for finalize_sendto() in milliseconds */
#define FINALIZE_SENDTO_DELAY (500)
/* empty the list */
void finalize_sendto(void)
{
ssize_t n;
struct scheduled_send * elt;
struct scheduled_send * next;
fd_set writefds;
struct timeval deadline;
struct timeval now;
struct timeval timeout;
int max_fd;
if(gettimeofday(&deadline, NULL) < 0) {
syslog(LOG_ERR, "gettimeofday: %m");
return;
}
deadline.tv_usec += FINALIZE_SENDTO_DELAY*1000;
if(deadline.tv_usec > 1000000) {
deadline.tv_sec++;
deadline.tv_usec -= 1000000;
}
while(send_list.lh_first) {
FD_ZERO(&writefds);
max_fd = -1;
for(elt = send_list.lh_first; elt != NULL; elt = next) {
next = elt->entries.le_next;
syslog(LOG_DEBUG, "finalize_sendto(): %d bytes on socket %d",
(int)elt->len, elt->sockfd);
n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags,
elt->dest_addr, elt->addrlen);
if(n < 0) {
if(errno==EAGAIN || errno==EWOULDBLOCK) {
FD_SET(elt->sockfd, &writefds);
if(elt->sockfd > max_fd)
max_fd = elt->sockfd;
continue;
}
syslog(LOG_WARNING, "finalize_sendto(): socket=%d sendto: %m", elt->sockfd);
}
/* remove from the list */
LIST_REMOVE(elt, entries);
free(elt);
}
/* check deadline */
if(gettimeofday(&now, NULL) < 0) {
syslog(LOG_ERR, "gettimeofday: %m");
return;
}
if(now.tv_sec > deadline.tv_sec ||
(now.tv_sec == deadline.tv_sec && now.tv_usec > deadline.tv_usec)) {
/* deadline ! */
while((elt = send_list.lh_first) != NULL) {
LIST_REMOVE(elt, entries);
free(elt);
}
return;
}
/* compute timeout value */
timeout.tv_sec = deadline.tv_sec - now.tv_sec;
timeout.tv_usec = deadline.tv_usec - now.tv_usec;
if(timeout.tv_usec < 0) {
timeout.tv_sec--;
timeout.tv_usec += 1000000;
}
if(max_fd >= 0) {
if(select(max_fd + 1, NULL, &writefds, NULL, &timeout) < 0) {
syslog(LOG_ERR, "select: %m");
return;
}
}
}
}

38
miniupnpd/asyncsendto.h Normal file
View File

@ -0,0 +1,38 @@
/* $Id: $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef ASYNCSENDTO_H_INCLUDED
#define ASYNCSENDTO_H_INCLUDED
/* sendto_schedule() : see sendto(2)
* schedule sendto() call after delay (milliseconds) */
ssize_t
sendto_schedule(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen,
unsigned int delay);
/* sendto_schedule() : see sendto(2)
* try sendto() at once and schedule if EINTR/EAGAIN/EWOULDBLOCK */
ssize_t
sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
/* get_next_scheduled_send()
* return number of scheduled sendto
* set next_send to timestamp to send next packet */
int get_next_scheduled_send(struct timeval * next_send);
/* execute sendto() for needed packets */
int try_sendto(fd_set * writefds);
/* set writefds before select() */
int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now);
/* empty the list */
void finalize_sendto(void);
#endif

View File

@ -1,6 +1,6 @@
/* $Id: commonrdr.h,v 1.7 2011/06/22 20:34:39 nanard Exp $ */
/* $Id: commonrdr.h,v 1.9 2014/02/11 09:36:15 nanard Exp $ */
/* MiniUPnP project
* (c) 2006-2011 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -10,6 +10,9 @@
#include "config.h"
/* init and shutdown functions */
/* init_redirect() return values :
* 0 : OK
* -1 : error */
int
init_redirect(void);
@ -17,7 +20,10 @@ void
shutdown_redirect(void);
/* get_redirect_rule() gets internal IP and port from
* interface, external port and protocl
* interface, external port and protocol
* return value :
* 0 success (rule found)
* -1 error or rule not found
*/
int
get_redirect_rule(const char * ifname, unsigned short eport, int proto,
@ -27,6 +33,10 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
unsigned int * timestamp,
u_int64_t * packets, u_int64_t * bytes);
/* get_redirect_rule_by_index()
* return values :
* 0 success (rule found)
* -1 error or rule not found */
int
get_redirect_rule_by_index(int index,
char * ifname, unsigned short * eport,

View File

@ -1,8 +1,8 @@
#! /bin/sh
# $Id: genconfig.sh,v 1.63 2013/05/03 09:30:10 nanard Exp $
# $Id: genconfig.sh,v 1.72 2014/03/10 10:17:17 nanard Exp $
# miniupnp daemon
# http://miniupnp.free.fr or http://miniupnp.tuxfamily.org/
# (c) 2006-2013 Thomas Bernard
# (c) 2006-2014 Thomas Bernard
# This software is subject to the conditions detailed in the
# LICENCE file provided within the distribution
@ -12,18 +12,15 @@ case "$argv" in
--igd2) IGD2=1 ;;
--strict) STRICT=1 ;;
--leasefile) LEASEFILE=1 ;;
--pcp) PCP=1 ;;
--pcp-peer)
PCP=1
PCP_PEER=1
;;
--vendorcfg) VENDORCFG=1 ;;
--pcp-peer) 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 " --vendorcfg enable configuration of manufacturer info"
echo " --pcp-peer enable PCP PEER operation"
exit 1
;;
@ -81,7 +78,7 @@ ${RM} ${CONFIGFILE}
echo "/* MiniUPnP Project" >> ${CONFIGFILE}
echo " * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/" >> ${CONFIGFILE}
echo " * (c) 2006-2013 Thomas Bernard" >> ${CONFIGFILE}
echo " * (c) 2006-2014 Thomas Bernard" >> ${CONFIGFILE}
echo " * generated by $0 on `date`" >> ${CONFIGFILE}
echo " * using command line options $* */" >> ${CONFIGFILE}
echo "#ifndef $CONFIGMACRO" >> ${CONFIGFILE}
@ -118,6 +115,7 @@ case $OS_NAME in
FW=pf
echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE}
OS_URL=http://www.openbsd.org/
V6SOCKETS_ARE_V6ONLY=`sysctl -n net.inet6.ip6.v6only`
;;
FreeBSD)
VER=`grep '#define __FreeBSD_version' /usr/include/sys/param.h | awk '{print $3}'`
@ -148,12 +146,14 @@ case $OS_NAME in
fi
echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE}
OS_URL=http://www.freebsd.org/
V6SOCKETS_ARE_V6ONLY=`sysctl -n net.inet6.ip6.v6only`
;;
pfSense)
# we need to detect if PFRULE_INOUT_COUNTS macro is needed
FW=pf
echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE}
OS_URL=http://www.pfsense.com/
V6SOCKETS_ARE_V6ONLY=`sysctl -n net.inet6.ip6.v6only`
;;
NetBSD)
if [ -f /etc/rc.subr ] && [ -f /etc/rc.conf ] ; then
@ -273,8 +273,15 @@ case $OS_NAME in
FW=netfilter
;;
Darwin)
MAJORVER=`echo $OS_VERSION | cut -d. -f1`
echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE}
# OS X switched to pf since 10.7 Lion (Darwin 11.0)
if [ $MAJORVER -ge 11 ] ; then
FW=pf
echo "#define PFRULE_INOUT_COUNTS" >> ${CONFIGFILE}
else
FW=ipfw
fi
OS_URL=http://developer.apple.com/macosx
;;
*)
@ -304,6 +311,11 @@ case $FW in
;;
esac
# set V6SOCKETS_ARE_V6ONLY to 0 if it was not set above
if [ -z "$V6SOCKETS_ARE_V6ONLY" ] ; then
V6SOCKETS_ARE_V6ONLY=0
fi
echo "Configuring compilation for [$OS_NAME] [$OS_VERSION] with [$FW] firewall software."
echo "Please edit config.h for more compilation options."
@ -332,15 +344,9 @@ 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
@ -352,9 +358,9 @@ echo "/*#define PCP_PEER*/" >> ${CONFIGFILE}
fi
echo "#ifdef PCP_PEER" >> ${CONFIGFILE}
echo "/*#define PCP_FLOWP*/" >> ${CONFIGFILE}
echo "#endif //PCP_PEER" >> ${CONFIGFILE}
echo "#endif /*PCP_PEER*/" >> ${CONFIGFILE}
echo "/*#define PCP_SADSCP*/" >> ${CONFIGFILE}
echo "#endif //ENABLE_PCP" >> ${CONFIGFILE}
echo "#endif /*ENABLE_PCP*/" >> ${CONFIGFILE}
echo "" >> ${CONFIGFILE}
echo "/* Uncomment the following line to enable generation of" >> ${CONFIGFILE}
@ -405,6 +411,15 @@ else
fi
echo "" >> ${CONFIGFILE}
echo "/* Define V6SOCKETS_ARE_V6ONLY if AF_INET6 sockets are restricted" >> ${CONFIGFILE}
echo " * to IPv6 communications only. */" >> ${CONFIGFILE}
if [ $V6SOCKETS_ARE_V6ONLY -eq 1 ] ; then
echo "#define V6SOCKETS_ARE_V6ONLY" >> ${CONFIGFILE}
else
echo "/*#define V6SOCKETS_ARE_V6ONLY*/" >> ${CONFIGFILE}
fi
echo "" >> ${CONFIGFILE}
echo "/* Enable the support of IGD v2 specification." >> ${CONFIGFILE}
echo " * This is not fully tested yet and can cause incompatibilities with some" >> ${CONFIGFILE}
echo " * control points, so enable with care. */" >> ${CONFIGFILE}
@ -448,6 +463,12 @@ else
fi
echo "" >> ${CONFIGFILE}
echo "/* If SSDP_RESPOND_SAME_VERSION is defined, the M-SEARCH response" >> ${CONFIGFILE}
echo " * include the same device version as was contained in the search" >> ${CONFIGFILE}
echo " * request. It conforms to UPnP DA v1.1 */" >> ${CONFIGFILE}
echo "#define SSDP_RESPOND_SAME_VERSION" >> ${CONFIGFILE}
echo "" >> ${CONFIGFILE}
echo "/* Add the optional Date: header in all HTTP responses */" >> ${CONFIGFILE}
if [ -n "$STRICT" ] ; then
echo "#define ENABLE_HTTP_DATE" >> ${CONFIGFILE}
@ -456,12 +477,24 @@ else
fi
echo "" >> ${CONFIGFILE}
echo "/* Wait a little before answering M-SEARCH request */" >> ${CONFIGFILE}
if [ -n "$STRICT" ] ; then
echo "#define DELAY_MSEARCH_RESPONSE" >> ${CONFIGFILE}
else
echo "/*#define DELAY_MSEARCH_RESPONSE*/" >> ${CONFIGFILE}
fi
echo "" >> ${CONFIGFILE}
echo "/* disable reading and parsing of config file (miniupnpd.conf) */" >> ${CONFIGFILE}
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 "/* Uncomment the following line to configure all manufacturer infos through miniupnpd.conf */" >> ${CONFIGFILE}
if [ -n "$VENDORCFG" ] ; then
echo "#define ENABLE_MANUFACTURER_INFO_CONFIGURATION" >> ${CONFIGFILE}
else
echo "/*#define ENABLE_MANUFACTURER_INFO_CONFIGURATION*/" >> ${CONFIGFILE}
fi
echo "" >> ${CONFIGFILE}
echo "#endif" >> ${CONFIGFILE}

View File

@ -1,4 +1,4 @@
/* $Id: getifaddr.c,v 1.17 2013/04/27 15:40:09 nanard Exp $ */
/* $Id: getifaddr.c,v 1.19 2013/12/13 14:28:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
@ -119,9 +119,16 @@ getifaddr(const char * ifname, char * buf, int len,
}
#ifdef ENABLE_PCP
int getifaddr_in6(const char * ifname, struct in6_addr * addr){
/* XXX I don't know if this function should return
* IPv4 or IPv6 if both are enabled... */
int getifaddr_in6(const char * ifname, struct in6_addr * addr)
{
struct ifaddrs * ifap;
struct ifaddrs * ife;
#ifdef ENABLE_IPV6
const struct sockaddr_in6 * tmpaddr;
#endif /* ENABLE_IPV6 */
int found = 0;
if(!ifname || ifname[0]=='\0')
return -1;
@ -130,9 +137,8 @@ int getifaddr_in6(const char * ifname, struct in6_addr * addr){
syslog(LOG_ERR, "getifaddrs: %m");
return -1;
}
for(ife = ifap; ife; ife = ife->ifa_next)
for(ife = ifap; ife && !found; ife = ife->ifa_next)
{
int found = 0;
/* skip other interfaces if one was specified */
if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
continue;
@ -141,32 +147,35 @@ int getifaddr_in6(const char * ifname, struct in6_addr * addr){
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);
/* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */
memset(addr->s6_addr, 0, 10);
addr->s6_addr[10] = 0xff;
addr->s6_addr[11] = 0xff;
memcpy(addr->s6_addr + 12,
&(((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr),
4);
found = 1;
break;
#ifdef ENABLE_IPV6
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));
tmpaddr = (const struct sockaddr_in6 *)ife->ifa_addr;
if(!IN6_IS_ADDR_LOOPBACK(&tmpaddr->sin6_addr)
&& !IN6_IS_ADDR_LINKLOCAL(&tmpaddr->sin6_addr))
{
memcpy(addr->s6_addr,
&tmpaddr->sin6_addr,
16);
found = 1;
}
break;
}
if (found) {
break;
#endif /* ENABLE_IPV6 */
}
}
freeifaddrs(ifap);
return 0;
return (found ? 0 : -1);
}
#endif
#endif /* ENABLE_PCP */
#ifdef ENABLE_IPV6
int

View File

@ -1,7 +1,7 @@
/* $Id: minissdp.c,v 1.54 2013/06/15 12:50:10 nanard Exp $ */
/* $Id: minissdp.c,v 1.61 2014/03/10 11:04:51 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -24,6 +24,7 @@
#include "minissdp.h"
#include "upnputils.h"
#include "getroute.h"
#include "asyncsendto.h"
#include "codelength.h"
/* SSDP ip/port */
@ -146,7 +147,11 @@ OpenAndConfSSDPReceiveSocket(int ipv6)
#ifdef ENABLE_IPV6
if(ipv6)
{
AddMulticastMembershipIPv6(s);
if(AddMulticastMembershipIPv6(s) < 0)
{
syslog(LOG_WARNING,
"Failed to add IPv6 multicast membership");
}
}
else
#endif
@ -276,9 +281,16 @@ OpenAndConfSSDPNotifySockets(int * sockets)
goto error;
i++;
#ifdef ENABLE_IPV6
if(GETFLAG(IPV6DISABLEDMASK))
{
sockets[i] = -1;
}
else
{
sockets[i] = OpenAndConfSSDPNotifySocketIPv6(lan_addr->index);
if(sockets[i] < 0)
goto error;
}
i++;
#endif
}
@ -319,11 +331,13 @@ EXT:
* st, st_len : ST: header
* suffix : suffix for USN: header
* host, port : our HTTP host, port
* delay : in milli-seconds
*/
static void
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)
const char * host, unsigned short port, const char * uuidvalue,
unsigned int delay)
{
int l, n;
char buf[512];
@ -388,15 +402,14 @@ SendSSDPResponse(int s, const struct sockaddr * addr,
}
addrlen = (addr->sa_family == AF_INET6)
? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
n = sendto(s, buf, l, 0,
addr, addrlen);
n = sendto_schedule(s, buf, l, 0,
addr, addrlen, delay);
sockaddr_to_string(addr, addr_str, sizeof(addr_str));
syslog(LOG_INFO, "SSDP Announce %d bytes to %s ST: %.*s",n,
addr_str,
l, buf);
if(n < 0)
{
/* XXX handle EINTR, EAGAIN, EWOULDBLOCK */
syslog(LOG_ERR, "sendto(udp): %m");
}
}
@ -477,7 +490,7 @@ SendSSDPNotify(int s, const struct sockaddr * dest,
syslog(LOG_WARNING, "SendSSDPNotify(): truncated output");
l = sizeof(bufr) - 1;
}
n = sendto(s, bufr, l, 0, dest,
n = sendto_or_schedule(s, bufr, l, 0, dest,
#ifdef ENABLE_IPV6
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)
#else
@ -486,7 +499,6 @@ SendSSDPNotify(int s, const struct sockaddr * dest,
);
if(n < 0)
{
/* XXX handle EINTR, EAGAIN, EWOULDBLOCK */
syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s,
host ? host : "NULL");
}
@ -494,6 +506,22 @@ SendSSDPNotify(int s, const struct sockaddr * dest,
{
syslog(LOG_NOTICE, "sendto() sent %d out of %d bytes", n, l);
}
/* Due to the unreliable nature of UDP, devices SHOULD send the entire
* set of discovery messages more than once with some delay between
* sets e.g. a few hundred milliseconds. To avoid network congestion
* discovery messages SHOULD NOT be sent more than three times. */
n = sendto_schedule(s, bufr, l, 0, dest,
#ifdef ENABLE_IPV6
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
#else
sizeof(struct sockaddr_in),
#endif
250);
if(n < 0)
{
syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s,
host ? host : "NULL");
}
}
static void
@ -564,8 +592,11 @@ SendSSDPNotifies2(int * sockets,
lifetime, 0);
i++;
#ifdef ENABLE_IPV6
if(sockets[i] >= 0)
{
SendSSDPNotifies(sockets[i], ipv6_addr_for_http_with_brackets, port,
lifetime, 1);
}
i++;
#endif
}
@ -620,8 +651,20 @@ ProcessSSDPData(int s, const char *bufr, int n,
#ifdef ENABLE_IPV6
char announced_host_buf[64];
#endif
#endif
#if defined(UPNP_STRICT) || defined(DELAY_MSEARCH_RESPONSE)
int mx_value = -1;
#endif
unsigned int delay = 0;
/* UPnP Device Architecture v1.1. 1.3.3 Search response :
* Devices responding to a multicast M-SEARCH SHOULD wait a random period
* of time between 0 seconds and the number of seconds specified in the
* MX field value of the search request before responding, in order to
* avoid flooding the requesting control point with search responses
* from multiple devices. If the search request results in the need for
* a multiple part response from the device, those multiple part
* responses SHOULD be spread at random intervals through the time period
* from 0 to the number of seconds specified in the MX header field. */
/* get the string representation of the sender address */
sockaddr_to_string(sender, sender_str, sizeof(sender_str));
@ -664,7 +707,7 @@ ProcessSSDPData(int s, const char *bufr, int n,
/*while(bufr[i+j]!='\r') j++;*/
/*syslog(LOG_INFO, "%.*s", j, bufr+i);*/
}
#ifdef UPNP_STRICT
#if defined(UPNP_STRICT) || defined(DELAY_MSEARCH_RESPONSE)
else if((i < n - 3) && (strncasecmp(bufr+i, "mx:", 3) == 0))
{
const char * mx;
@ -682,16 +725,32 @@ ProcessSSDPData(int s, const char *bufr, int n,
#endif
}
#ifdef UPNP_STRICT
/* For multicast M-SEARCH requests, if the search request does
* not contain an MX header field, the device MUST silently
* discard and ignore the search request. */
if(mx_value < 0) {
syslog(LOG_INFO, "ignoring SSDP packet missing MX: header");
return;
} else if(mx_value > 5) {
/* If the MX header field specifies a field value greater
* than 5, the device SHOULD assume that it contained the
* value 5 or less. */
mx_value = 5;
}
#elif defined(DELAY_MSEARCH_RESPONSE)
if(mx_value < 0) {
mx_value = 1;
} else if(mx_value > 5) {
/* If the MX header field specifies a field value greater
* than 5, the device SHOULD assume that it contained the
* value 5 or less. */
mx_value = 5;
}
#endif
/*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s",
sender_str );*/
if(st && (st_len > 0))
{
/* TODO : doesnt answer at once but wait for a random time */
syslog(LOG_INFO, "SSDP M-SEARCH from %s ST: %.*s",
sender_str, st_len, st);
/* find in which sub network the client is */
@ -753,11 +812,43 @@ ProcessSSDPData(int s, const char *bufr, int n,
#endif
)
{
/* SSDP_RESPOND_SAME_VERSION :
* response is urn:schemas-upnp-org:service:WANIPConnection:1 when
* M-SEARCH included urn:schemas-upnp-org:service:WANIPConnection:1
* else the implemented versions is included in the response
*
* From UPnP Device Architecture v1.1 :
* 1.3.2 [...] Updated versions of device and service types
* are REQUIRED to be fully backward compatible with
* previous versions. Devices MUST respond to M-SEARCH
* requests for any supported version. For example, if a
* device implements urn:schemas-upnporg:service:xyz:2,
* it MUST respond to search requests for both that type
* and urn:schemas-upnp-org:service:xyz:1. The response
* MUST specify the same version as was contained in the
* search request. [...] */
#ifndef SSDP_RESPOND_SAME_VERSION
if(i==0)
ver_str[0] = '\0';
else
snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version);
#endif
syslog(LOG_INFO, "Single search found");
#ifdef DELAY_MSEARCH_RESPONSE
delay = random() / (1 + RAND_MAX / (1000 * mx_value));
#ifdef DEBUG
syslog(LOG_DEBUG, "mx=%dsec delay=%ums", mx_value, delay);
#endif
#endif
SendSSDPResponse(s, sender,
#ifdef SSDP_RESPOND_SAME_VERSION
st, st_len, "",
#else
known_service_types[i].s, l, ver_str,
#endif
announced_host, port,
known_service_types[i].uuid);
known_service_types[i].uuid,
delay);
break;
}
}
@ -765,9 +856,15 @@ ProcessSSDPData(int s, const char *bufr, int n,
/* strlen("ssdp:all") == 8 */
if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8)))
{
#ifdef DELAY_MSEARCH_RESPONSE
unsigned int delay_increment = (mx_value * 1000) / 15;
#endif
syslog(LOG_INFO, "ssdp:all found");
for(i=0; known_service_types[i].s; i++)
{
#ifdef DELAY_MSEARCH_RESPONSE
delay += delay_increment;
#endif
if(i==0)
ver_str[0] = '\0';
else
@ -776,37 +873,53 @@ ProcessSSDPData(int s, const char *bufr, int n,
SendSSDPResponse(s, sender,
known_service_types[i].s, l, ver_str,
announced_host, port,
known_service_types[i].uuid);
known_service_types[i].uuid,
delay);
}
/* also answer for uuid */
#ifdef DELAY_MSEARCH_RESPONSE
delay += delay_increment;
#endif
SendSSDPResponse(s, sender, uuidvalue_igd, strlen(uuidvalue_igd), "",
announced_host, port, uuidvalue_igd);
announced_host, port, uuidvalue_igd, delay);
#ifdef DELAY_MSEARCH_RESPONSE
delay += delay_increment;
#endif
SendSSDPResponse(s, sender, uuidvalue_wan, strlen(uuidvalue_wan), "",
announced_host, port, uuidvalue_wan);
announced_host, port, uuidvalue_wan, delay);
#ifdef DELAY_MSEARCH_RESPONSE
delay += delay_increment;
#endif
SendSSDPResponse(s, sender, uuidvalue_wcd, strlen(uuidvalue_wcd), "",
announced_host, port, uuidvalue_wcd);
announced_host, port, uuidvalue_wcd, delay);
}
/* responds to request by UUID value */
l = (int)strlen(uuidvalue_igd);
if(l==st_len)
{
#ifdef DELAY_MSEARCH_RESPONSE
delay = random() / (1 + RAND_MAX / (1000 * mx_value));
#endif
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);
announced_host, port, uuidvalue_igd,
delay);
}
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);
announced_host, port, uuidvalue_wan,
delay);
}
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);
announced_host, port, uuidvalue_wcd,
delay);
}
}
}
@ -856,7 +969,7 @@ SendSSDPbyebye(int s, const struct sockaddr * dest,
syslog(LOG_WARNING, "SendSSDPbyebye(): truncated output");
l = sizeof(bufr) - 1;
}
n = sendto(s, bufr, l, 0, dest,
n = sendto_or_schedule(s, bufr, l, 0, dest,
#ifdef ENABLE_IPV6
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)
#else
@ -1013,6 +1126,8 @@ SubmitServicesToMiniSSDPD(const char * host, unsigned short port) {
while(n > 0) {
l = write(s, p, n);
if (l < 0) {
if(errno == EINTR)
continue;
syslog(LOG_ERR, "write(): %m");
close(s);
return -1;

View File

@ -1,7 +1,7 @@
/* $Id: miniupnpd.c,v 1.176 2013/06/13 13:21:29 nanard Exp $ */
/* $Id: miniupnpd.c,v 1.189 2014/03/10 11:04:52 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -63,6 +63,7 @@
#include "miniupnpdtypes.h"
#include "daemonize.h"
#include "upnpevents.h"
#include "asyncsendto.h"
#ifdef ENABLE_NATPMP
#include "natpmp.h"
#ifdef ENABLE_PCP
@ -111,12 +112,17 @@ volatile sig_atomic_t should_send_public_address_change_notif = 0;
/* OpenAndConfHTTPSocket() :
* setup the socket used to handle incoming HTTP connections. */
static int
#ifdef ENABLE_IPV6
OpenAndConfHTTPSocket(unsigned short port, int ipv6)
#else
OpenAndConfHTTPSocket(unsigned short port)
#endif
{
int s;
int i = 1;
#ifdef ENABLE_IPV6
struct sockaddr_in6 listenname;
struct sockaddr_in6 listenname6;
struct sockaddr_in listenname4;
#else
struct sockaddr_in listenname;
#endif
@ -124,7 +130,7 @@ OpenAndConfHTTPSocket(unsigned short port)
if( (s = socket(
#ifdef ENABLE_IPV6
PF_INET6,
ipv6 ? PF_INET6 : PF_INET,
#else
PF_INET,
#endif
@ -153,19 +159,35 @@ OpenAndConfHTTPSocket(unsigned short port)
}
#ifdef ENABLE_IPV6
memset(&listenname, 0, sizeof(struct sockaddr_in6));
listenname.sin6_family = AF_INET6;
listenname.sin6_port = htons(port);
listenname.sin6_addr = in6addr_any;
if(ipv6)
{
memset(&listenname6, 0, sizeof(struct sockaddr_in6));
listenname6.sin6_family = AF_INET6;
listenname6.sin6_port = htons(port);
listenname6.sin6_addr = in6addr_any;
listenname_len = sizeof(struct sockaddr_in6);
} else {
memset(&listenname4, 0, sizeof(struct sockaddr_in));
listenname4.sin_family = AF_INET;
listenname4.sin_port = htons(port);
listenname4.sin_addr.s_addr = htonl(INADDR_ANY);
listenname_len = sizeof(struct sockaddr_in);
}
#else
memset(&listenname, 0, sizeof(struct sockaddr_in));
listenname.sin_family = AF_INET;
listenname.sin_port = htons(port);
listenname.sin_addr.s_addr = htonl(INADDR_ANY);
listenname_len = sizeof(struct sockaddr_in);
#endif
#ifdef ENABLE_IPV6
if(bind(s,
ipv6 ? (struct sockaddr *)&listenname6 : (struct sockaddr *)&listenname4,
listenname_len) < 0)
#else
if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0)
#endif
{
syslog(LOG_ERR, "bind(http): %m");
close(s);
@ -181,6 +203,85 @@ OpenAndConfHTTPSocket(unsigned short port)
return s;
}
static struct upnphttp *
ProcessIncomingHTTP(int shttpl)
{
int shttp;
socklen_t clientnamelen;
#ifdef ENABLE_IPV6
struct sockaddr_storage clientname;
clientnamelen = sizeof(struct sockaddr_storage);
#else
struct sockaddr_in clientname;
clientnamelen = sizeof(struct sockaddr_in);
#endif
shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
if(shttp<0)
{
/* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
syslog(LOG_ERR, "accept(http): %m");
}
else
{
struct upnphttp * tmp = 0;
char addr_str[64];
sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
syslog(LOG_INFO, "HTTP connection from %s", addr_str);
if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
{
/* The peer is not a LAN ! */
syslog(LOG_WARNING,
"HTTP peer %s is not from a LAN, closing the connection",
addr_str);
close(shttp);
}
else
{
/* Create a new upnphttp object and add it to
* the active upnphttp object list */
tmp = New_upnphttp(shttp);
if(tmp)
{
#ifdef ENABLE_IPV6
if(clientname.ss_family == AF_INET)
{
tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
}
else if(clientname.ss_family == AF_INET6)
{
struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
{
memcpy(&tmp->clientaddr,
&addr->sin6_addr.s6_addr[12],
4);
}
else
{
tmp->ipv6 = 1;
memcpy(&tmp->clientaddr_v6,
&addr->sin6_addr,
sizeof(struct in6_addr));
}
}
#else
tmp->clientaddr = clientname.sin_addr;
#endif
return tmp;
}
else
{
syslog(LOG_ERR, "New_upnphttp() failed");
close(shttp);
}
}
}
return NULL;
}
#ifdef ENABLE_NFQUEUE
int identify_ip_protocol(char *payload) {
@ -586,6 +687,7 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str)
p++;
if(*p=='.')
{
/* parse mask in /255.255.255.0 format */
while(*p && (*p=='.' || isdigit(*p)))
p++;
n = p - q;
@ -598,6 +700,7 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str)
}
else
{
/* it is a /24 format */
int nbits = atoi(q);
if(nbits > 32 || nbits < 0)
goto parselan_error;
@ -685,7 +788,10 @@ void complete_uuidvalues(void)
* 5) check and write pid file
* 6) set startup time stamp
* 7) compute presentation URL
* 8) set signal handlers */
* 8) set signal handlers
* 9) init random generator (srandom())
* 10) init redirection engine
* 11) reload mapping from leasefile */
static int
init(int argc, char * * argv, struct runtime_vars * v)
{
@ -906,12 +1012,14 @@ init(int argc, char * * argv, struct runtime_vars * v)
optionsfile);
}
}
/* if lifetimes ae inverse*/
#ifdef ENABLE_PCP
/* if lifetimes are 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
}
#endif /* DISABLE_CONFIG_FILE */
@ -1241,6 +1349,10 @@ init(int argc, char * * argv, struct runtime_vars * v)
syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1");
}
/* initialize random number generator */
srandom((unsigned int)time(NULL));
/* initialize redirection engine (and pinholes) */
if(init_redirect() < 0)
{
syslog(LOG_ERR, "Failed to init redirection engine. EXITING");
@ -1338,12 +1450,15 @@ main(int argc, char * * argv)
{
int i;
int shttpl = -1; /* socket for HTTP */
#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
int shttpl_v4 = -1; /* socket for HTTP (ipv4 only) */
#endif
int sudp = -1; /* IP v4 socket for receiving SSDP */
#ifdef ENABLE_IPV6
int sudpv6 = -1; /* IP v6 socket for receiving SSDP */
#endif
#ifdef ENABLE_NATPMP
int * snatpmp = NULL;
int * snatpmp = NULL; /* also used for PCP */
#endif
#ifdef ENABLE_NFQUEUE
int nfqh = -1;
@ -1429,7 +1544,11 @@ main(int argc, char * * argv)
{
/* open socket for HTTP connections. Listen on the 1st LAN address */
#ifdef ENABLE_IPV6
shttpl = OpenAndConfHTTPSocket((v.port > 0) ? v.port : 0, 1);
#else /* ENABLE_IPV6 */
shttpl = OpenAndConfHTTPSocket((v.port > 0) ? v.port : 0);
#endif /* ENABLE_IPV6 */
if(shttpl < 0)
{
syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
@ -1445,13 +1564,22 @@ main(int argc, char * * argv)
v.port = ntohs(sockinfo.sin_port);
}
syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
shttpl_v4 = OpenAndConfHTTPSocket(v.port, 0);
if(shttpl_v4 < 0)
{
syslog(LOG_ERR, "Failed to open socket for HTTP on port %hu (IPv4). EXITING", v.port);
return 1;
}
#endif /* V6SOCKETS_ARE_V6ONLY */
#ifdef ENABLE_IPV6
if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) {
syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s",
ipv6_addr_for_http_with_brackets);
} else {
memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
syslog(LOG_WARNING, "no HTTP IPv6 address");
syslog(LOG_WARNING, "no HTTP IPv6 address, disabling IPv6");
SETFLAG(IPV6DISABLEDMASK);
}
#endif
@ -1466,11 +1594,14 @@ main(int argc, char * * argv)
}
}
#ifdef ENABLE_IPV6
if(!GETFLAG(IPV6DISABLEDMASK))
{
sudpv6 = OpenAndConfSSDPReceiveSocket(1);
if(sudpv6 < 0)
{
syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
}
}
#endif
/* open socket for sending notifications */
@ -1513,9 +1644,6 @@ main(int argc, char * * argv)
syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
NATPMP_PORT);
}
#endif
#if 0
ScanNATPMPforExpiration();
#endif
}
#endif
@ -1548,7 +1676,7 @@ main(int argc, char * * argv)
/* send public address change notifications if needed */
if(should_send_public_address_change_notif)
{
syslog(LOG_DEBUG, "should send external iface address change notification(s)");
syslog(LOG_INFO, "should send external iface address change notification(s)");
#ifdef ENABLE_NATPMP
if(GETFLAG(ENABLENATPMPMASK))
SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count);
@ -1629,28 +1757,6 @@ main(int argc, char * * argv)
syslog(LOG_DEBUG, "setting timeout to %u sec",
(unsigned)timeout.tv_sec);
}
#ifdef ENABLE_NATPMP
#if 0
/* Remove expired NAT-PMP mappings */
while(nextnatpmptoclean_timestamp
&& (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time))
{
/*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/
if(CleanExpiredNATPMP() < 0) {
syslog(LOG_ERR, "CleanExpiredNATPMP() failed");
break;
}
}
if(nextnatpmptoclean_timestamp
&& timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec))
{
/*syslog(LOG_DEBUG, "setting timeout to %d sec",
nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/
timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec;
timeout.tv_usec = 0;
}
#endif
#endif
#ifdef ENABLE_6FC_SERVICE
/* Clean up expired IPv6 PinHoles */
next_pinhole_ts = 0;
@ -1683,6 +1789,13 @@ main(int argc, char * * argv)
FD_SET(shttpl, &readset);
max_fd = MAX( max_fd, shttpl);
}
#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
if (shttpl_v4 >= 0)
{
FD_SET(shttpl_v4, &readset);
max_fd = MAX( max_fd, shttpl_v4);
}
#endif
#ifdef ENABLE_IPV6
if (sudpv6 >= 0)
{
@ -1748,6 +1861,38 @@ main(int argc, char * * argv)
upnpevents_selectfds(&readset, &writeset, &max_fd);
#endif
/* queued "sendto" */
{
struct timeval next_send;
i = get_next_scheduled_send(&next_send);
if(i > 0) {
#ifdef DEBUG
syslog(LOG_DEBUG, "%d queued sendto", i);
#endif
i = get_sendto_fds(&writeset, &max_fd, &timeofday);
if(timeofday.tv_sec > next_send.tv_sec ||
(timeofday.tv_sec == next_send.tv_sec && timeofday.tv_usec >= next_send.tv_usec)) {
if(i > 0) {
timeout.tv_sec = 0;
timeout.tv_usec = 0;
}
} else {
struct timeval tmp_timeout;
tmp_timeout.tv_sec = (next_send.tv_sec - timeofday.tv_sec);
tmp_timeout.tv_usec = (next_send.tv_usec - timeofday.tv_usec);
if(tmp_timeout.tv_usec < 0) {
tmp_timeout.tv_usec += 1000000;
tmp_timeout.tv_sec--;
}
if(timeout.tv_sec > tmp_timeout.tv_sec
|| (timeout.tv_sec == tmp_timeout.tv_sec && timeout.tv_usec > tmp_timeout.tv_usec)) {
timeout.tv_sec = tmp_timeout.tv_sec;
timeout.tv_usec = tmp_timeout.tv_usec;
}
}
}
}
if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
{
if(quitting) goto shutdown;
@ -1756,6 +1901,9 @@ main(int argc, char * * argv)
syslog(LOG_ERR, "Failed to select open sockets. EXITING");
return 1; /* very serious cause of error */
}
if(try_sendto(&writeset) < 0) {
syslog(LOG_ERR, "try_sendto: %m");
}
#ifdef USE_MINIUPNPDCTL
for(ectl = ctllisthead.lh_first; ectl;)
{
@ -1837,10 +1985,10 @@ main(int argc, char * * argv)
if (len < 1)
continue;
#ifdef ENABLE_PCP
if (msg_buff[0]==0) { // version equals to 0 -> means NAT-PMP
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
} else { /* everything else can be PCP */
ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len,
&senderaddr);
}
@ -1886,79 +2034,24 @@ main(int argc, char * * argv)
/* process incoming HTTP connections */
if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
{
int shttp;
socklen_t clientnamelen;
#ifdef ENABLE_IPV6
struct sockaddr_storage clientname;
clientnamelen = sizeof(struct sockaddr_storage);
#else
struct sockaddr_in clientname;
clientnamelen = sizeof(struct sockaddr_in);
#endif
shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
if(shttp<0)
{
/* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
syslog(LOG_ERR, "accept(http): %m");
}
else
{
struct upnphttp * tmp = 0;
char addr_str[64];
sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
syslog(LOG_INFO, "HTTP connection from %s", addr_str);
if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
{
/* The peer is not a LAN ! */
syslog(LOG_WARNING,
"HTTP peer %s is not from a LAN, closing the connection",
addr_str);
close(shttp);
}
else
{
/* Create a new upnphttp object and add it to
* the active upnphttp object list */
tmp = New_upnphttp(shttp);
struct upnphttp * tmp;
tmp = ProcessIncomingHTTP(shttpl);
if(tmp)
{
#ifdef ENABLE_IPV6
if(clientname.ss_family == AF_INET)
{
tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
}
else if(clientname.ss_family == AF_INET6)
{
struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
{
memcpy(&tmp->clientaddr,
&addr->sin6_addr.s6_addr[12],
4);
}
else
{
tmp->ipv6 = 1;
memcpy(&tmp->clientaddr_v6,
&addr->sin6_addr,
sizeof(struct in6_addr));
}
}
#else
tmp->clientaddr = clientname.sin_addr;
#endif
LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
}
else
}
#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
if(shttpl_v4 >= 0 && FD_ISSET(shttpl_v4, &readset))
{
syslog(LOG_ERR, "New_upnphttp() failed");
close(shttp);
}
}
struct upnphttp * tmp;
tmp = ProcessIncomingHTTP(shttpl_v4);
if(tmp)
{
LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
}
}
#endif
#ifdef ENABLE_NFQUEUE
/* process NFQ packets */
if(nfqh >= 0 && FD_ISSET(nfqh, &readset))
@ -1982,6 +2075,22 @@ main(int argc, char * * argv)
} /* end of main loop */
shutdown:
syslog(LOG_NOTICE, "shutting down MiniUPnPd");
/* send good-bye */
if (GETFLAG(ENABLEUPNPMASK))
{
#ifndef ENABLE_IPV6
if(SendSSDPGoodbye(snotify, addr_count) < 0)
#else
if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
#endif
{
syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
}
}
/* try to send pending packets */
finalize_sendto();
/* close out open sockets */
while(upnphttphead.lh_first != NULL)
{
@ -1992,6 +2101,9 @@ shutdown:
if (sudp >= 0) close(sudp);
if (shttpl >= 0) close(shttpl);
#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
if (shttpl_v4 >= 0) close(shttpl_v4);
#endif
#ifdef ENABLE_IPV6
if (sudpv6 >= 0) close(sudpv6);
#endif
@ -2021,14 +2133,6 @@ shutdown:
if (GETFLAG(ENABLEUPNPMASK))
{
#ifndef ENABLE_IPV6
if(SendSSDPGoodbye(snotify, addr_count) < 0)
#else
if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
#endif
{
syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
}
#ifndef ENABLE_IPV6
for(i = 0; i < addr_count; i++)
#else
@ -2037,6 +2141,7 @@ shutdown:
close(snotify[i]);
}
/* remove pidfile */
if(pidfilename && (unlink(pidfilename) < 0))
{
syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);

View File

@ -1,10 +1,10 @@
/* $Id: minixml.c,v 1.9 2011/02/07 13:44:57 nanard Exp $ */
/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */
/* minixml.c : the minimum size a xml parser can be ! */
/* Project : miniupnp
* webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
Copyright (c) 2005-2011, Thomas BERNARD
Copyright (c) 2005-2014, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -113,7 +113,20 @@ static void parseelt(struct xmlparser * p)
const char * elementname;
while(p->xml < (p->xmlend - 1))
{
if((p->xml)[0]=='<' && (p->xml)[1]!='?')
if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "<!--", 4)))
{
p->xml += 3;
/* ignore comments */
do
{
p->xml++;
if ((p->xml + 3) >= p->xmlend)
return;
}
while(memcmp(p->xml, "-->", 3) != 0);
p->xml += 3;
}
else if((p->xml)[0]=='<' && (p->xml)[1]!='?')
{
i = 0; elementname = ++p->xml;
while( !IS_WHITE_SPACE(*p->xml)

View File

@ -1,6 +1,6 @@
/* $Id: natpmp.c,v 1.33 2013/03/23 10:46:55 nanard Exp $ */
/* $Id: natpmp.c,v 1.39 2014/03/07 10:43:30 nanard Exp $ */
/* MiniUPnP project
* (c) 2007-2013 Thomas Bernard
* (c) 2007-2014 Thomas Bernard
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -24,6 +24,7 @@
#include "commonrdr.h"
#include "upnputils.h"
#include "portinuse.h"
#include "asyncsendto.h"
#ifdef ENABLE_NATPMP
@ -158,8 +159,6 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
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];
@ -266,10 +265,39 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
}
}
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)) {
} else if(iport==0) {
resp[3] = 2; /* Not Authorized/Refused */
} else do {
} else { /* iport > 0 && lifetime > 0 */
unsigned short eport_first = 0;
int any_eport_allowed = 0;
char desc[64];
while(resp[3] == 0) {
if(eport_first == 0) { /* first time in loop */
eport_first = eport;
} else if(eport == eport_first) { /* no eport available */
if(any_eport_allowed == 0) { /* all eports rejected by permissions */
syslog(LOG_ERR, "No allowed eport for NAT-PMP %hu %s->%s:%hu",
eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport);
resp[3] = 2; /* Not Authorized/Refused */
} else { /* at least one eport allowed (but none available) */
syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu",
eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport);
resp[3] = 4; /* Out of resources */
}
break;
}
if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) {
eport++;
if(eport == 0) eport++; /* skip port zero */
continue;
}
any_eport_allowed = 1; /* at lease one eport is allowed */
if (port_in_use(ext_if_name, eport, proto, senderaddrstr, iport)) {
syslog(LOG_INFO, "port %hu protocol %s already in use", eport, (proto==IPPROTO_TCP)?"tcp":"udp");
eport++;
if(eport == 0) eport++; /* skip port zero */
continue;
}
r = get_redirect_rule(ext_if_name, eport, proto,
iaddr_old, sizeof(iaddr_old),
&iport_old, 0, 0, 0, 0,
@ -287,17 +315,11 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
}
} else {
eport++;
if(eport == 0) eport++; /* skip port zero */
continue;
}
}
if (port_in_use(ext_if_name, eport, proto, senderaddrstr, iport)) {
syslog(LOG_INFO, "port %hu protocol %s already in use", eport, (proto==IPPROTO_TCP)?"tcp":"udp");
eport++;
r = 0;
continue;
}
{ /* do the redirection */
char desc[64];
/* do the redirection */
#if 0
timestamp = (unsigned)(time(NULL) - startup_time)
+ lifetime;
@ -314,17 +336,10 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'",
eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc);
resp[3] = 3; /* Failure */
#if 0
} else if( !nextnatpmptoclean_eport
|| timestamp < nextnatpmptoclean_timestamp) {
nextnatpmptoclean_timestamp = timestamp;
nextnatpmptoclean_eport = eport;
nextnatpmptoclean_proto = proto;
#endif
}
break;
}
} while(r==0);
}
*((uint16_t *)(resp+8)) = htons(iport); /* private port */
*((uint16_t *)(resp+10)) = htons(eport); /* public port */
*((uint32_t *)(resp+12)) = htonl(lifetime); /* Port Mapping lifetime */
@ -334,7 +349,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
default:
resp[3] = 5; /* Unsupported OPCODE */
}
n = sendto(s, resp, resplen, 0,
n = sendto_or_schedule(s, resp, resplen, 0,
(struct sockaddr *)senderaddr, sizeof(*senderaddr));
if(n<0) {
syslog(LOG_ERR, "sendto(natpmp): %m");
@ -344,67 +359,6 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
}
}
#if 0
/* iterate through the redirection list to find those who came
* from NAT-PMP and select the first to expire */
int ScanNATPMPforExpiration()
{
char desc[64];
unsigned short iport, eport;
int proto;
int r, i;
unsigned timestamp;
nextnatpmptoclean_eport = 0;
nextnatpmptoclean_timestamp = 0;
for(i = 0; ; i++) {
r = get_redirect_rule_by_index(i, 0, &eport, 0, 0,
&iport, &proto, desc, sizeof(desc),
&timestamp, 0, 0);
if(r<0)
break;
if(sscanf(desc, "NAT-PMP %u", &timestamp) == 1) {
if( !nextnatpmptoclean_eport
|| timestamp < nextnatpmptoclean_timestamp) {
nextnatpmptoclean_eport = eport;
nextnatpmptoclean_proto = proto;
nextnatpmptoclean_timestamp = timestamp;
syslog(LOG_DEBUG, "set nextnatpmptoclean_timestamp to %u", timestamp);
}
}
}
return 0;
}
/* remove the next redirection that is expired
*/
int CleanExpiredNATPMP()
{
char desc[64];
unsigned timestamp;
unsigned short iport;
if(get_redirect_rule(ext_if_name, nextnatpmptoclean_eport,
nextnatpmptoclean_proto,
0, 0,
&iport, desc, sizeof(desc), &timestamp, 0, 0) < 0)
return ScanNATPMPforExpiration();
/* check desc - this is important since we keep expiration time as part
* of the desc.
* If the rule is renewed, timestamp and nextnatpmptoclean_timestamp
* can be different. In that case, the rule must not be removed ! */
if(sscanf(desc, "NAT-PMP %u", &timestamp) == 1) {
if(timestamp > nextnatpmptoclean_timestamp)
return ScanNATPMPforExpiration();
}
/* remove redirection then search for next one:) */
if(_upnp_delete_redir(nextnatpmptoclean_eport, nextnatpmptoclean_proto)<0)
return -1;
syslog(LOG_INFO, "Expired NAT-PMP mapping port %hu %s removed",
nextnatpmptoclean_eport,
nextnatpmptoclean_proto==IPPROTO_TCP?"TCP":"UDP");
return ScanNATPMPforExpiration();
}
#endif
/* SendNATPMPPublicAddressChangeNotification()
* should be called when the public IP address changed */
void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets)
@ -449,7 +403,7 @@ void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets)
#endif
/* Port to use in 2006 version of the NAT-PMP specification */
sockname.sin_port = htons(NATPMP_PORT);
n = sendto(sockets[j], notif, 12, 0,
n = sendto_or_schedule(sockets[j], notif, 12, 0,
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in));
if(n < 0)
{
@ -459,7 +413,7 @@ void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets)
}
/* Port to use in 2008 version of the NAT-PMP specification */
sockname.sin_port = htons(NATPMP_NOTIF_PORT);
n = sendto(sockets[j], notif, 12, 0,
n = sendto_or_schedule(sockets[j], notif, 12, 0,
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in));
if(n < 0)
{

View File

@ -1,4 +1,4 @@
/* $Id: natpmp.h,v 1.8 2011/05/27 21:36:22 nanard Exp $ */
/* $Id: natpmp.h,v 1.11 2014/02/01 17:17:35 nanard Exp $ */
/* MiniUPnP project
* author : Thomas Bernard
* website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
@ -26,12 +26,6 @@ int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr_in* senderaddr,
void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
struct sockaddr_in *senderaddr);
#if 0
int ScanNATPMPforExpiration(void);
int CleanExpiredNATPMP(void);
#endif
void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets);
#endif

View File

@ -1,4 +1,4 @@
/* $Id: options.c,v 1.26 2012/06/29 19:26:09 nanard Exp $ */
/* $Id: options.c,v 1.28 2013/12/13 14:07:08 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* author: Ryan Wagoner
@ -16,7 +16,7 @@
#include "upnppermissions.h"
#ifdef PCP_SADSCP
#include "pcplearndscp.h"
#endif // PCP_SADSPC
#endif /* PCP_SADSPC */
#include "upnpglobalvars.h"
#ifndef DISABLE_CONFIG_FILE
@ -187,7 +187,7 @@ readoptionsfile(const char * fname)
}
continue;
}
#endif //PCP_SADSCP
#endif /* PCP_SADSCP */
if(!(equals = strchr(name, '=')))
{
fprintf(stderr, "parsing error file %s line %d : %s\n",
@ -303,7 +303,7 @@ freeoptions(void)
dscp_values_list = NULL;
num_dscp_values = 0;
}
#endif //PCP_SADSCP
#endif /* PCP_SADSCP */
}
#endif /* DISABLE_CONFIG_FILE */

View File

@ -1,4 +1,4 @@
/* $Id: pcp_msg_struct.h $ */
/* $Id: pcp_msg_struct.h,v 1.3 2013/12/16 16:02:19 nanard Exp $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Peter Tatrai
@ -138,7 +138,7 @@ typedef enum pcp_options {
#ifdef WIN32
#pragma warning (push)
#pragma warning (disable:4200)
#endif // WIN32
#endif /* WIN32 */
#pragma pack(push, 1)
@ -148,7 +148,7 @@ typedef struct pcp_request {
uint8_t r_opcode;
uint16_t reserved;
uint32_t req_lifetime;
uint32_t ip[4]; /* ipv4 will be represented
struct in6_addr ip; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint8_t next_data[0];
} pcp_request_t;
@ -182,7 +182,7 @@ typedef struct pcp_map_v2 {
uint8_t reserved[3];
uint16_t int_port;
uint16_t ext_port;
uint32_t ext_ip[4]; /* ipv4 will be represented
struct in6_addr ext_ip; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint8_t next_data[0];
} pcp_map_v2_t;
@ -193,7 +193,7 @@ typedef struct pcp_map_v1 {
uint8_t reserved[3];
uint16_t int_port;
uint16_t ext_port;
uint32_t ext_ip[4]; /* ipv4 will be represented
struct in6_addr ext_ip; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint8_t next_data[0];
} pcp_map_v1_t;
@ -204,11 +204,11 @@ typedef struct pcp_peer_v1 {
uint8_t reserved[3];
uint16_t int_port;
uint16_t ext_port;
uint32_t ext_ip[4]; /* ipv4 will be represented
struct in6_addr ext_ip; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint16_t peer_port;
uint16_t reserved1;
uint32_t peer_ip[4];
struct in6_addr peer_ip;
uint8_t next_data[0];
} pcp_peer_v1_t;
@ -219,11 +219,11 @@ typedef struct pcp_peer_v2 {
uint8_t reserved[3];
uint16_t int_port;
uint16_t ext_port;
uint32_t ext_ip[4]; /* ipv4 will be represented
struct in6_addr ext_ip; /* ipv4 will be represented
by the ipv4 mapped ipv6 */
uint16_t peer_port;
uint16_t reserved1;
uint32_t peer_ip[4];
struct in6_addr peer_ip;
uint8_t next_data[0];
} pcp_peer_v2_t;
@ -254,7 +254,7 @@ typedef struct pcp_3rd_party_option{
uint8_t option;
uint8_t reserved;
uint16_t len;
uint32_t ip[4];
struct in6_addr ip;
uint8_t next_data[0];
} pcp_3rd_party_option_t;
@ -280,11 +280,11 @@ typedef struct pcp_filter_option {
uint8_t reserved2;
uint8_t prefix_len;
uint16_t peer_port;
uint32_t peer_ip[4];
struct in6_addr peer_ip;
}pcp_filter_option_t;
#pragma pack(pop)
#ifdef WIN32
#pragma warning (pop)
#endif // WIN32
#endif /* WIN32 */

View File

@ -1,4 +1,4 @@
/* $Id: pcplearndscp.h $ */
/* $Id: pcplearndscp.h,v 1.2 2013/12/13 15:47:23 nanard Exp $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Miroslav Bagljas
@ -44,8 +44,8 @@ struct dscp_values {
// #set_learn_dscp "Webex" 1 1 1 34
/* #set_learn_dscp "Webex" 1 1 1 34 */
int
read_learn_dscp_line(struct dscp_values *dscpvalues, char *p);
#endif // PCPLEARNDSCP_H_INCLUDED
#endif /* PCPLEARNDSCP_H_INCLUDED */

View File

@ -1,4 +1,4 @@
/* $Id: pcpserver.c $ */
/* $Id: pcpserver.c,v 1.12 2014/02/28 17:50:22 nanard Exp $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Peter Tatrai
@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
@ -58,33 +59,21 @@ POSSIBILITY OF SUCH DAMAGE.
#include "upnpredirect.h"
#include "commonrdr.h"
#include "getifaddr.h"
#include "asyncsendto.h"
#include "pcp_msg_struct.h"
#ifdef PCP_PEER
//TODO make this platform independent
/* TODO make this platform independent */
#include "netfilter/iptcrdr.h"
#endif
#define IPV6_ADDR_COPY(dest, src) \
do { \
(dest)[0] = (src)[0]; \
(dest)[1] = (src)[1]; \
(dest)[2] = (src)[2]; \
(dest)[3] = (src)[3]; \
} while (0)
typedef struct options_occur {
int third_party_occur;
int pfailure_occur;
} options_occur_t;
/* server specific information */
struct pcp_server_info {
uint8_t server_version;
};
/* default server settings, highest version supported is the default */
struct pcp_server_info this_server_info = {2};
static struct pcp_server_info this_server_info = {2};
/* structure holding information from PCP msg*/
/* all variables are in host byte order except IP addresses */
@ -104,7 +93,7 @@ typedef struct pcp_info {
#ifdef PCP_PEER
uint16_t peer_port;
const struct in6_addr *peer_ip; /* Destination IP in network order */
#endif //PCP_PEER
#endif /* PCP_PEER */
#ifdef PCP_SADSCP
/* SADSCP specific information */
@ -129,7 +118,7 @@ typedef struct pcp_info {
int pfailure_present;
char senderaddrstr[INET_ADDRSTRLEN];
}pcp_info_t;
} pcp_info_t;
#ifdef PCP_SADSCP
@ -191,7 +180,7 @@ static int parseCommonRequestHeader(pcp_request_t *common_req, pcp_info_t *pcp_m
pcp_msg_info->version = common_req->ver ;
pcp_msg_info->opcode = common_req->r_opcode &0x7f ;
pcp_msg_info->lifetime = ntohl(common_req->req_lifetime);
pcp_msg_info->int_ip = (struct in6_addr*)common_req->ip;
pcp_msg_info->int_ip = &common_req->ip;
if ( (common_req->ver > this_server_info.server_version) ) {
@ -219,7 +208,7 @@ static void printMAPOpcodeVersion1(pcp_map_v1_t *map_buf)
syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", ntohs(map_buf->int_port) );
syslog(LOG_DEBUG, "MAP ext port: \t\t %d\n", ntohs(map_buf->ext_port) );
syslog(LOG_DEBUG, "MAP Ext IP: \t\t %s\n", inet_ntop(AF_INET6,
map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN));
&map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN));
}
static void printMAPOpcodeVersion2(pcp_map_v2_t *map_buf)
@ -230,11 +219,11 @@ static void printMAPOpcodeVersion2(pcp_map_v2_t *map_buf)
syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", ntohs(map_buf->int_port) );
syslog(LOG_DEBUG, "MAP ext port: \t\t %d\n", ntohs(map_buf->ext_port) );
syslog(LOG_DEBUG, "MAP Ext IP: \t\t %s\n", inet_ntop(AF_INET6,
map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN));
&map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN));
}
#endif //DEBUG
#endif /* DEBUG */
static int parsePCPMAP_version1(pcp_map_v1_t *map_v1, \
static int parsePCPMAP_version1(pcp_map_v1_t *map_v1,
pcp_info_t *pcp_msg_info)
{
pcp_msg_info->is_map_op = 1;
@ -242,7 +231,7 @@ static int parsePCPMAP_version1(pcp_map_v1_t *map_v1, \
pcp_msg_info->int_port = ntohs(map_v1->int_port);
pcp_msg_info->ext_port = ntohs(map_v1->ext_port);
pcp_msg_info->ext_ip = (struct in6_addr*)map_v1->ext_ip;
pcp_msg_info->ext_ip = &(map_v1->ext_ip);
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){
syslog(LOG_ERR, "PCP MAP: Protocol was ZERO, but internal port has non-ZERO value.");
@ -252,7 +241,7 @@ static int parsePCPMAP_version1(pcp_map_v1_t *map_v1, \
return 0;
}
static int parsePCPMAP_version2(pcp_map_v2_t *map_v2, \
static int parsePCPMAP_version2(pcp_map_v2_t *map_v2,
pcp_info_t *pcp_msg_info)
{
pcp_msg_info->is_map_op = 1;
@ -260,7 +249,7 @@ static int parsePCPMAP_version2(pcp_map_v2_t *map_v2, \
pcp_msg_info->int_port = ntohs(map_v2->int_port);
pcp_msg_info->ext_port = ntohs(map_v2->ext_port);
pcp_msg_info->ext_ip = (struct in6_addr*)map_v2->ext_ip;
pcp_msg_info->ext_ip = &(map_v2->ext_ip);
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ) {
syslog(LOG_ERR, "PCP MAP: Protocol was ZERO, but internal port has non-ZERO value.");
@ -280,10 +269,10 @@ static void printPEEROpcodeVersion1(pcp_peer_v1_t *peer_buf)
syslog(LOG_DEBUG, "PCP PEER: v1 Opcode specific information. \n");
syslog(LOG_DEBUG, "Protocol: \t\t %d\n",peer_buf->protocol );
syslog(LOG_DEBUG, "Internal port: \t\t %d\n", ntohs(peer_buf->int_port) );
syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, peer_buf->ext_ip,
syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->ext_ip,
ext_addr,INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "External port port: \t\t %d\n", ntohs(peer_buf->ext_port) );
syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, peer_buf->peer_ip,
syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->peer_ip,
peer_addr,INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "PEER port port: \t\t %d\n", ntohs(peer_buf->peer_port) );
}
@ -296,14 +285,14 @@ static void printPEEROpcodeVersion2(pcp_peer_v2_t *peer_buf)
syslog(LOG_DEBUG, "PCP PEER: v2 Opcode specific information. \n");
syslog(LOG_DEBUG, "Protocol: \t\t %d\n",peer_buf->protocol );
syslog(LOG_DEBUG, "Internal port: \t\t %d\n", ntohs(peer_buf->int_port) );
syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, peer_buf->ext_ip,
syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->ext_ip,
ext_addr,INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "External port port: \t\t %d\n", ntohs(peer_buf->ext_port) );
syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, peer_buf->peer_ip,
syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->peer_ip,
peer_addr,INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "PEER port port: \t\t %d\n", ntohs(peer_buf->peer_port) );
}
#endif //DEBUG
#endif /* DEBUG */
/*
* Function extracting information from peer_buf to pcp_msg_info
@ -318,8 +307,8 @@ static int parsePCPPEER_version1(pcp_peer_v1_t *peer_buf, \
pcp_msg_info->ext_port = ntohs(peer_buf->ext_port);
pcp_msg_info->peer_port = ntohs(peer_buf->peer_port);
pcp_msg_info->ext_ip = (struct in6_addr*)peer_buf->ext_ip;
pcp_msg_info->peer_ip = (struct in6_addr*)peer_buf->peer_ip;
pcp_msg_info->ext_ip = &peer_buf->ext_ip;
pcp_msg_info->peer_ip = &peer_buf->peer_ip;
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){
syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value.");
@ -342,8 +331,8 @@ static int parsePCPPEER_version2(pcp_peer_v2_t *peer_buf, \
pcp_msg_info->ext_port = ntohs(peer_buf->ext_port);
pcp_msg_info->peer_port = ntohs(peer_buf->peer_port);
pcp_msg_info->ext_ip = (struct in6_addr*)peer_buf->ext_ip;
pcp_msg_info->peer_ip = (struct in6_addr*)peer_buf->peer_ip;
pcp_msg_info->ext_ip = &peer_buf->ext_ip;
pcp_msg_info->peer_ip = &peer_buf->peer_ip;
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){
syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value.");
@ -352,7 +341,7 @@ static int parsePCPPEER_version2(pcp_peer_v2_t *peer_buf, \
}
return 0;
}
#endif //PCP_PEER
#endif /* PCP_PEER */
#ifdef PCP_SADSCP
#ifdef DEBUG
@ -399,8 +388,8 @@ static int parseSADSCP(pcp_sadscp_req_t *sadscp, pcp_info_t *pcp_msg_info) {
}
#endif
static int parsePCPOptions(void* pcp_buf, int* remainingSize, int* processedSize, \
pcp_info_t *pcp_msg_info)
static int parsePCPOptions(void* pcp_buf, int* remainingSize,
int* processedSize, pcp_info_t *pcp_msg_info)
{
int remain = *remainingSize;
int processed = *processedSize;
@ -436,7 +425,7 @@ static int parsePCPOptions(void* pcp_buf, int* remainingSize, int* processedSize
#ifdef DEBUG
syslog(LOG_DEBUG, "PCP OPTION: \t Third party \n");
syslog(LOG_DEBUG, "Third PARTY IP: \t %s\n", inet_ntop(AF_INET6,
opt_3rd->ip, third_addr, INET6_ADDRSTRLEN));
&(opt_3rd->ip), third_addr, INET6_ADDRSTRLEN));
#endif
if (pcp_msg_info->thirdp_present != 0 ) {
@ -481,7 +470,7 @@ static int parsePCPOptions(void* pcp_buf, int* remainingSize, int* processedSize
break;
case PCP_OPTION_FILTER:
// TODO fully implement filter
/* TODO fully implement filter */
opt_filter = (pcp_filter_option_t*) (pcp_buf + processed);
option_length = ntohs(opt_filter->len);
@ -538,7 +527,7 @@ static int parsePCPOptions(void* pcp_buf, int* remainingSize, int* processedSize
break;
}
// shift processed and remaining values to new values
/* shift processed and remaining values to new values */
*remainingSize = remain;
*processedSize = processed;
return pcp_msg_info->result_code;
@ -547,6 +536,7 @@ static int parsePCPOptions(void* pcp_buf, int* remainingSize, int* processedSize
static int CheckExternalAddress(pcp_info_t* pcp_msg_info)
{
/* can contain a IPv4-mapped IPv6 address */
static struct in6_addr external_addr;
if(use_ext_ip_addr) {
@ -565,13 +555,14 @@ static int CheckExternalAddress(pcp_info_t* pcp_msg_info)
pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE;
return -1;
}
/* how do we know which address we need ? IPv6 or IPv4 ? */
if(getifaddr_in6(ext_if_name, &external_addr) < 0) {
pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE;
return -1;
}
}
if (IN6_IS_ADDR_UNSPECIFIED(pcp_msg_info->ext_ip)) {
if (pcp_msg_info->ext_ip == NULL || IN6_IS_ADDR_UNSPECIFIED(pcp_msg_info->ext_ip)) {
pcp_msg_info->ext_ip = &external_addr;
@ -616,8 +607,7 @@ static void FillSA(struct sockaddr *sa, const struct in6_addr *in6,
} else {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
sa6->sin6_family = AF_INET6;
IPV6_ADDR_COPY((uint32_t*)sa6->sin6_addr.s6_addr,
(uint32_t*)in6->s6_addr);
sa6->sin6_addr = *in6;
sa6->sin6_port = htons(port);
}
}
@ -675,7 +665,7 @@ static int CreatePCPPeer(pcp_info_t *pcp_msg_info)
return 0;
}
}
//Create Peer Mapping
/* Create Peer Mapping */
{
char desc[64];
char peerip_s[INET_ADDRSTRLEN], extip_s[INET_ADDRSTRLEN];
@ -724,7 +714,7 @@ static int CreatePCPPeer(pcp_info_t *pcp_msg_info)
}
}
#endif
//TODO: add upnp function for PI
/* TODO: add upnp function for PI */
if (add_peer_redirect_rule2(ext_if_name,
peerip_s,
pcp_msg_info->peer_port,
@ -810,20 +800,48 @@ static void DeletePCPPeer(pcp_info_t *pcp_msg_info)
pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES;
}
}
#endif //PCP_PEER
#endif /* PCP_PEER */
static void CreatePCPMap(pcp_info_t *pcp_msg_info)
{
char desc[64];
char iaddr_old[INET_ADDRSTRLEN];
uint16_t iport_old;
unsigned int timestamp = time(NULL) + pcp_msg_info->lifetime;
uint16_t eport_first = 0;
int any_eport_allowed = 0;
unsigned int timestamp;
int r=0;
if (pcp_msg_info->ext_port == 0) {
pcp_msg_info->ext_port = pcp_msg_info->int_port;
}
do {
if (eport_first == 0) { /* first time in loop */
eport_first = pcp_msg_info->ext_port;
} else if (pcp_msg_info->ext_port == eport_first) { /* no eport available */
if (any_eport_allowed == 0) { /* all eports rejected by permissions */
pcp_msg_info->result_code = PCP_ERR_NOT_AUTHORIZED;
} else { /* at least one eport allowed (but none available) */
pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES;
}
return;
}
if ((IN6_IS_ADDR_V4MAPPED(pcp_msg_info->int_ip) &&
(!check_upnp_rule_against_permissions(upnppermlist,
num_upnpperm, pcp_msg_info->ext_port,
((struct in_addr*)pcp_msg_info->int_ip->s6_addr)[3],
pcp_msg_info->int_port)))) {
if (pcp_msg_info->pfailure_present) {
pcp_msg_info->result_code = PCP_ERR_CANNOT_PROVIDE_EXTERNAL;
return;
}
pcp_msg_info->ext_port++;
if (pcp_msg_info->ext_port == 0) { /* skip port zero */
pcp_msg_info->ext_port++;
}
continue;
}
any_eport_allowed = 1;
r = get_redirect_rule(ext_if_name,
pcp_msg_info->ext_port,
pcp_msg_info->protocol,
@ -841,24 +859,26 @@ static void CreatePCPMap(pcp_info_t *pcp_msg_info)
return;
}
} else {
syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing",
pcp_msg_info->ext_port, (pcp_msg_info->protocol==IPPROTO_TCP)?"tcp":"udp",
iaddr_old, iport_old);
/* remove and then add again */
if (_upnp_delete_redir(pcp_msg_info->ext_port,
pcp_msg_info->protocol)==0) {
break;
}
}
pcp_msg_info->ext_port++;
}
} while (r==0);
if ((pcp_msg_info->ext_port == 0) ||
(IN6_IS_ADDR_V4MAPPED(pcp_msg_info->int_ip) &&
(!check_upnp_rule_against_permissions(upnppermlist,
num_upnpperm, pcp_msg_info->ext_port,
((struct in_addr*)pcp_msg_info->int_ip->s6_addr)[3],
pcp_msg_info->int_port)))) {
} else if (pcp_msg_info->pfailure_present) {
pcp_msg_info->result_code = PCP_ERR_CANNOT_PROVIDE_EXTERNAL;
return;
}
}
pcp_msg_info->ext_port++;
if (pcp_msg_info->ext_port == 0) { /* skip port zero */
pcp_msg_info->ext_port++;
}
}
} while (r==0);
timestamp = time(NULL) + pcp_msg_info->lifetime;
snprintf(desc, sizeof(desc), "PCP %hu %s",
pcp_msg_info->ext_port,
@ -879,6 +899,8 @@ static void CreatePCPMap(pcp_info_t *pcp_msg_info)
pcp_msg_info->int_port,
desc);
pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES;
} else {
syslog(LOG_INFO, "PCP MAP: added mapping %s %hu->%s:%hu '%s'",
(pcp_msg_info->protocol==IPPROTO_TCP)?"TCP":"UDP",
@ -903,7 +925,7 @@ static void DeletePCPMap(pcp_info_t *pcp_msg_info)
char desc[64];
unsigned int timestamp;
//iterate through all rules and delete the requested ones
/* iterate through all rules and delete the requested ones */
while(get_redirect_rule_by_index(index, 0,
&eport2, iaddr2, sizeof(iaddr2),
&iport2, &proto2,
@ -912,7 +934,7 @@ static void DeletePCPMap(pcp_info_t *pcp_msg_info)
if(0 == strncmp(iaddr2, pcp_msg_info->senderaddrstr, sizeof(iaddr2))
&& (proto2==proto)
&& (0 == strncmp(desc, "PCP", 3)) //starts with PCP
&& (0 == strncmp(desc, "PCP", 3)) /* starts with PCP */
&& ((iport2==iport) || (iport==0))) {
r = _upnp_delete_redir(eport2, proto2);
@ -984,26 +1006,31 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
#ifdef PCP_SADSCP
pcp_sadscp_req_t* sadscp;
#endif
// start with PCP_SUCCESS as result code, if everything is OK value will be unchanged
/* start with PCP_SUCCESS as result code, if everything is OK value will be unchanged */
pcp_msg_info->result_code = PCP_SUCCESS;
remainingSize = req_size;
processedSize = 0;
// discard request that exceeds maximal length,
// or that is shorter than 3
// or that is not the multiple of 4
if (req_size < PCP_MIN_LEN)
return 0; //ignore msg
/* discard request that exceeds maximal length,
or that is shorter than PCP_MIN_LEN (=24)
or that is not the multiple of 4 */
if (req_size < 3)
return 0; /* ignore msg */
if (req_size < PCP_MIN_LEN) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return 1; /* send response */
}
if ( (req_size > PCP_MAX_LEN) || ( (req_size & 3) != 0)) {
syslog(LOG_ERR, "PCP: Size of PCP packet(%d) is larger than %d bytes or "
"the size is not multiple of 4.\n", req_size, PCP_MAX_LEN);
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return 1; // send response
return 1; /* send response */
}
//first print out info from common request header
/* first print out info from common request header */
common_req = (pcp_request_t*)req;
if (parseCommonRequestHeader(common_req, pcp_msg_info) ) {
@ -1014,7 +1041,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
processedSize += sizeof(pcp_request_t);
if (common_req->ver == 1) {
/* legacy PCP version 1 support */
switch ( common_req->r_opcode & 0x7F ) {
case PCP_OPCODE_MAP:
@ -1027,7 +1054,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
map_v1 = (pcp_map_v1_t*)(req + processedSize);
#ifdef DEBUG
printMAPOpcodeVersion1(map_v1);
#endif //DEBUG
#endif /* DEBUG */
if ( parsePCPMAP_version1(map_v1, pcp_msg_info) ) {
return pcp_msg_info->result_code;
}
@ -1062,7 +1089,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
#ifdef DEBUG
printPEEROpcodeVersion1(peer_v1);
#endif //DEBUG
#endif /* DEBUG */
if ( parsePCPPEER_version1(peer_v1, pcp_msg_info) ) {
return pcp_msg_info->result_code;
}
@ -1085,15 +1112,20 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
break;
#endif //PCP_PEER
#endif /* PCP_PEER */
default:
pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPCODE;
break;
}
} else if (common_req->ver == 2) {
/* RFC 6887 PCP support
* http://tools.ietf.org/html/rfc6887 */
switch ( common_req->r_opcode & 0x7F) {
case PCP_OPCODE_ANNOUNCE:
/* should check PCP Client's IP Address in request */
/* see http://tools.ietf.org/html/rfc6887#section-14.1 */
break;
case PCP_OPCODE_MAP:
remainingSize -= sizeof(pcp_map_v2_t);
@ -1106,7 +1138,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
#ifdef DEBUG
printMAPOpcodeVersion2(map_v2);
#endif //DEBUG
#endif /* DEBUG */
if (parsePCPMAP_version2(map_v2, pcp_msg_info) ) {
return pcp_msg_info->result_code;
@ -1142,7 +1174,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
#ifdef DEBUG
printPEEROpcodeVersion2(peer_v2);
#endif //DEBUG
#endif /* DEBUG */
parsePCPPEER_version2(peer_v2, pcp_msg_info);
processedSize += sizeof(pcp_peer_v2_t);
@ -1165,7 +1197,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
}
break;
#endif //PCP_PEER
#endif /* PCP_PEER */
#ifdef PCP_SADSCP
case PCP_OPCODE_SADSCP:
@ -1225,7 +1257,7 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info)
resp->result_code = pcp_msg_info->result_code;
resp->epochtime = htonl(time(NULL) - startup_time);
switch (pcp_msg_info->result_code) {
//long lifetime errors
/*long lifetime errors*/
case PCP_ERR_UNSUPP_VERSION:
case PCP_ERR_NOT_AUTHORIZED:
case PCP_ERR_MALFORMED_REQUEST:
@ -1254,15 +1286,13 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info)
if (resp->r_opcode == 0x81) { /* MAP response */
if (resp->ver == 1 ) {
pcp_map_v1_t *mapr = (pcp_map_v1_t *)resp->next_data;
IPV6_ADDR_COPY((uint32_t*)mapr->ext_ip,
(uint32_t*)pcp_msg_info->ext_ip);
mapr->ext_ip = *pcp_msg_info->ext_ip;
mapr->ext_port = htons(pcp_msg_info->ext_port);
mapr->int_port = htons(pcp_msg_info->int_port);
}
else if (resp->ver == 2 ) {
pcp_map_v2_t *mapr = (pcp_map_v2_t *)resp->next_data;
IPV6_ADDR_COPY((uint32_t*)mapr->ext_ip,
(uint32_t*)pcp_msg_info->ext_ip);
mapr->ext_ip = *pcp_msg_info->ext_ip;
mapr->ext_port = htons(pcp_msg_info->ext_port);
mapr->int_port = htons(pcp_msg_info->int_port);
}
@ -1274,19 +1304,17 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info)
peer_resp->ext_port = htons(pcp_msg_info->ext_port);
peer_resp->int_port = htons(pcp_msg_info->int_port);
peer_resp->peer_port = htons(pcp_msg_info->peer_port);
IPV6_ADDR_COPY((uint32_t*)peer_resp->ext_ip,
(uint32_t*)pcp_msg_info->ext_ip);
peer_resp->ext_ip = *pcp_msg_info->ext_ip;
}
else if (resp->ver == 2 ){
pcp_peer_v2_t* peer_resp = (pcp_peer_v2_t*)resp->next_data;
peer_resp->ext_port = htons(pcp_msg_info->ext_port);
peer_resp->int_port = htons(pcp_msg_info->int_port);
peer_resp->peer_port = htons(pcp_msg_info->peer_port);
IPV6_ADDR_COPY((uint32_t*)peer_resp->ext_ip,
(uint32_t*)pcp_msg_info->ext_ip);
peer_resp->ext_ip = *pcp_msg_info->ext_ip;
}
}
#endif //PCP_PEER
#endif /* PCP_PEER */
#ifdef PCP_SADSCP
else if (resp->r_opcode == 0x83) { /*SADSCP response*/
@ -1296,10 +1324,10 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info)
sadscp_resp->a_r_dscp_value |= (pcp_msg_info->sadscp_dscp & PCP_SADSCP_MASK);
memset(sadscp_resp->reserved, 0, sizeof(sadscp_resp->reserved));
}
#endif //PCP_SADSCP
#endif /* PCP_SADSCP */
}
int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, \
int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len,
struct sockaddr_in *senderaddr)
{
pcp_info_t pcp_msg_info;
@ -1323,11 +1351,11 @@ int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, \
createPCPResponse(buff, &pcp_msg_info);
if ((len&0x03)!=0) {
len = len+4-(len&0x03); //round up resp. length to multiple of 4
}
len = sendto(s, buff, len, 0,
if(len < PCP_MIN_LEN)
len = PCP_MIN_LEN;
else
len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */
len = sendto_or_schedule(s, buff, len, 0,
(struct sockaddr *)senderaddr, sizeof(struct sockaddr_in));
if( len < 0 ) {
syslog(LOG_ERR, "sendto(pcpserver): %m");

View File

@ -1,4 +1,4 @@
/* $Id: pcpserver.h $ */
/* $Id: pcpserver.h,v 1.2 2013/12/13 15:48:39 nanard Exp $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Peter Tatrai
@ -36,10 +36,12 @@ POSSIBILITY OF SUCH DAMAGE.
#define PCP_MIN_LEN 24
#define PCP_MAX_LEN 1100
struct sockaddr_in;
/*
* returns 0 upon success 1 otherwise
*/
int ProcessIncomingPCPPacket(int s, unsigned char *msg_buff, int len, \
int ProcessIncomingPCPPacket(int s, unsigned char *msg_buff, int len,
struct sockaddr_in *senderaddr);
#endif /* PCPSERVER_H_INCLUDED */

View File

@ -1,7 +1,7 @@
/* $Id: obsdrdr.c,v 1.74 2012/05/01 09:20:43 nanard Exp $ */
/* $Id: obsdrdr.c,v 1.80 2014/03/06 13:02:46 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -9,15 +9,19 @@
* pf rules created (with ext_if = xl1)
* - OpenBSD up to version 4.6 :
* rdr pass on xl1 inet proto udp from any to any port = 54321 \
* label "test label" -> 192.168.0.141 port 12345
* or a rdr rule + a pass rule
* keep state label "test label" -> 192.168.0.42 port 12345
* or a rdr rule + a pass rule :
* rdr quick on xl1 inet proto udp from any to any port = 54321 \
* keep state label "test label" -> 192.168.0.42 port 12345
* pass in quick on xl1 inet proto udp from any to 192.168.0.42 port = 12345 \
* flags S/SA keep state label "test label"
*
* - OpenBSD starting from version 4.7
* match in on xl1 inet proto udp from any to any port 54321 \
* label "test label" rdr-to 192.168.0.141 port 12345
* label "test label" rdr-to 192.168.0.42 port 12345
* or
* pass in quick on xl1 inet proto udp from any to any port 54321 \
* label "test label" rdr-to 192.168.0.141 port 12345
* label "test label" rdr-to 192.168.0.42 port 12345
*
*
*
@ -45,6 +49,9 @@
#ifdef __DragonFly__
#include <net/pf/pfvar.h>
#else
#ifdef MACOSX
#define PRIVATE 1
#endif
#include <net/pfvar.h>
#endif
#include <fcntl.h>
@ -173,6 +180,45 @@ clear_redirect_rules(void)
error:
return -1;
}
int
clear_filter_rules(void)
{
#ifndef PF_ENABLE_FILTER_RULES
return 0;
#else
struct pfioc_trans io;
struct pfioc_trans_e ioe;
if(dev<0) {
syslog(LOG_ERR, "pf device is not open");
return -1;
}
memset(&ioe, 0, sizeof(ioe));
io.size = 1;
io.esize = sizeof(ioe);
io.array = &ioe;
#ifndef PF_NEWSTYLE
ioe.rs_num = PF_RULESET_FILTER;
#else
/* ? */
ioe.type = PF_TRANS_RULESET;
#endif
strlcpy(ioe.anchor, anchor_name, MAXPATHLEN);
if(ioctl(dev, DIOCXBEGIN, &io) < 0)
{
syslog(LOG_ERR, "ioctl(dev, DIOCXBEGIN, ...): %m");
goto error;
}
if(ioctl(dev, DIOCXCOMMIT, &io) < 0)
{
syslog(LOG_ERR, "ioctl(dev, DIOCXCOMMIT, ...): %m");
goto error;
}
return 0;
error:
return -1;
#endif
}
#endif
/* add_redirect_rule2() :
@ -219,9 +265,15 @@ add_redirect_rule2(const char * ifname,
pcr.rule.rdr.addr.type = PF_ADDR_ADDRMASK;
#endif
#ifdef MACOSX
pcr.rule.dst.xport.range.op = PF_OP_EQ;
pcr.rule.dst.xport.range.port[0] = htons(eport);
pcr.rule.dst.xport.range.port[1] = htons(eport);
#else
pcr.rule.dst.port_op = PF_OP_EQ;
pcr.rule.dst.port[0] = htons(eport);
pcr.rule.dst.port[1] = htons(eport);
#endif
#ifndef PF_NEWSTYLE
pcr.rule.action = PF_RDR;
#ifndef PF_ENABLE_FILTER_RULES
@ -338,8 +390,11 @@ add_filter_rule2(const char * ifname,
struct pfioc_rule pcr;
#ifndef PF_NEWSTYLE
struct pfioc_pooladdr pp;
struct pf_pooladdr *a;
#endif
#ifndef USE_IFNAME_IN_RULES
UNUSED(ifname);
#endif
UNUSED(eport);
if(dev<0) {
syslog(LOG_ERR, "pf device is not open");
return -1;
@ -363,9 +418,8 @@ add_filter_rule2(const char * ifname,
if(1)
{
#endif
pcr.rule.dst.port_op = PF_OP_EQ;
pcr.rule.dst.port[0] = htons(eport);
pcr.rule.dst.port[0] = htons(iport);
pcr.rule.direction = PF_IN;
pcr.rule.action = PF_PASS;
pcr.rule.af = AF_INET;
@ -398,33 +452,16 @@ add_filter_rule2(const char * ifname,
inet_pton(AF_INET, rhost, &pcr.rule.src.addr.v.a.addr.v4.s_addr);
pcr.rule.src.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
}
#ifndef PF_NEWSTYLE
pcr.rule.rpool.proxy_port[0] = eport;
a = calloc(1, sizeof(struct pf_pooladdr));
inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);
a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
memcpy(&pp.addr, a, sizeof(struct pf_pooladdr));
TAILQ_INIT(&pcr.rule.rpool.list);
inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);
TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries);
/* we have any - any port = # keep state label */
/* we want any - iaddr port = # keep state label */
/* memcpy(&pcr.rule.dst, a, sizeof(struct pf_pooladdr)); */
memcpy(&pp.addr, a, sizeof(struct pf_pooladdr));
strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
if(ioctl(dev, DIOCADDADDR, &pp) < 0)
{
syslog(LOG_ERR, "ioctl(dev, DIOCADDADDR, ...): %m");
r = -1;
}
else
{
#else
inet_pton(AF_INET, iaddr, &pcr.rule.dst.addr.v.a.addr.v4.s_addr);
pcr.rule.dst.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
#ifndef PF_NEWSTYLE
pcr.rule.rpool.proxy_port[0] = iport;
pcr.rule.rpool.proxy_port[1] = iport;
TAILQ_INIT(&pcr.rule.rpool.list);
#endif
if(1)
{
#endif
pcr.action = PF_CHANGE_GET_TICKET;
if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
{
@ -441,9 +478,6 @@ add_filter_rule2(const char * ifname,
}
}
}
#ifndef PF_NEWSTYLE
free(a);
#endif
}
return r;
#endif
@ -490,8 +524,13 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
goto error;
}
#ifdef MACOSX
if( (eport == ntohs(pr.rule.dst.xport.range.port[0]))
&& (eport == ntohs(pr.rule.dst.xport.range.port[1]))
#else
if( (eport == ntohs(pr.rule.dst.port[0]))
&& (eport == ntohs(pr.rule.dst.port[1]))
#endif
&& (pr.rule.proto == proto) )
{
#ifndef PF_NEWSTYLE
@ -561,8 +600,10 @@ error:
return -1;
}
int
delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
static int
priv_delete_redirect_rule(const char * ifname, unsigned short eport,
int proto, unsigned short * iport,
in_addr_t * iaddr)
{
int i, n;
struct pfioc_rule pr;
@ -591,10 +632,53 @@ delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
goto error;
}
#ifdef MACOSX
if( (eport == ntohs(pr.rule.dst.xport.range.port[0]))
&& (eport == ntohs(pr.rule.dst.xport.range.port[1]))
#else
if( (eport == ntohs(pr.rule.dst.port[0]))
&& (eport == ntohs(pr.rule.dst.port[1]))
#endif
&& (pr.rule.proto == proto) )
{
/* retrieve iport in order to remove filter rule */
#ifndef PF_NEWSTYLE
if(iport) *iport = pr.rule.rpool.proxy_port[0];
if(iaddr)
{
/* retrieve internal address */
struct pfioc_pooladdr pp;
memset(&pp, 0, sizeof(pp));
strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
pp.r_action = PF_RDR;
pp.r_num = i;
pp.ticket = pr.ticket;
if(ioctl(dev, DIOCGETADDRS, &pp) < 0)
{
syslog(LOG_ERR, "ioctl(dev, DIOCGETADDRS, ...): %m");
goto error;
}
if(pp.nr != 1)
{
syslog(LOG_NOTICE, "No address associated with pf rule");
goto error;
}
pp.nr = 0; /* first */
if(ioctl(dev, DIOCGETADDR, &pp) < 0)
{
syslog(LOG_ERR, "ioctl(dev, DIOCGETADDR, ...): %m");
goto error;
}
*iaddr = pp.addr.addr.v.a.addr.v4.s_addr;
}
#else
if(iport) *iport = pr.rule.rdr.proxy_port[0];
if(iaddr)
{
/* retrieve internal address */
*iaddr = pr.rule.rdr.addr.v.a.addr.v4.s_addr;
}
#endif
pr.action = PF_CHANGE_GET_TICKET;
if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
{
@ -617,14 +701,23 @@ error:
}
int
delete_filter_rule(const char * ifname, unsigned short eport, int proto)
delete_redirect_rule(const char * ifname, unsigned short eport,
int proto)
{
return priv_delete_redirect_rule(ifname, eport, proto, NULL, NULL);
}
static int
priv_delete_filter_rule(const char * ifname, unsigned short iport,
int proto, in_addr_t iaddr)
{
#ifndef PF_ENABLE_FILTER_RULES
UNUSED(ifname); UNUSED(eport); UNUSED(proto);
UNUSED(ifname); UNUSED(iport); UNUSED(proto);
return 0;
#else
int i, n;
struct pfioc_rule pr;
UNUSED(ifname);
if(dev<0) {
syslog(LOG_ERR, "pf device is not open");
return -1;
@ -646,8 +739,16 @@ delete_filter_rule(const char * ifname, unsigned short eport, int proto)
syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
goto error;
}
if( (eport == ntohs(pr.rule.dst.port[0]))
&& (pr.rule.proto == proto) )
#ifdef TEST
syslog(LOG_DEBUG, "%2d port=%hu proto=%d addr=%8x",
i, ntohs(pr.rule.dst.port[0]), pr.rule.proto,
pr.rule.dst.addr.v.a.addr.v4.s_addr);
/*pr.rule.dst.addr.v.a.mask.v4.s_addr*/
#endif
if( (iport == ntohs(pr.rule.dst.port[0]))
&& (pr.rule.proto == proto) &&
(iaddr == pr.rule.dst.addr.v.a.addr.v4.s_addr)
)
{
pr.action = PF_CHANGE_GET_TICKET;
if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
@ -670,6 +771,21 @@ error:
#endif
}
int
delete_redirect_and_filter_rules(const char * ifname, unsigned short eport,
int proto)
{
int r;
unsigned short iport;
in_addr_t iaddr;
r = priv_delete_redirect_rule(ifname, eport, proto, &iport, &iaddr);
if(r == 0)
{
r = priv_delete_filter_rule(ifname, iport, proto, iaddr);
}
return r;
}
int
get_redirect_rule_by_index(int index,
char * ifname, unsigned short * eport,
@ -710,7 +826,11 @@ get_redirect_rule_by_index(int index,
goto error;
}
*proto = pr.rule.proto;
#ifdef MACOSX
*eport = ntohs(pr.rule.dst.xport.range.port[0]);
#else
*eport = ntohs(pr.rule.dst.port[0]);
#endif
#ifndef PF_NEWSTYLE
*iport = pr.rule.rpool.proxy_port[0];
#else
@ -822,8 +942,13 @@ get_portmappings_in_range(unsigned short startport, unsigned short endport,
syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
continue;
}
#ifdef MACOSX
eport = ntohs(pr.rule.dst.xport.range.port[0]);
if( (eport == ntohs(pr.rule.dst.xport.range.port[1]))
#else
eport = ntohs(pr.rule.dst.port[0]);
if( (eport == ntohs(pr.rule.dst.port[1]))
#endif
&& (pr.rule.proto == proto)
&& (startport <= eport) && (eport <= endport) )
{

View File

@ -1,7 +1,7 @@
/* $Id: obsdrdr.h,v 1.20 2012/03/05 20:36:20 nanard Exp $ */
/* $Id: obsdrdr.h,v 1.23 2014/03/06 12:24:33 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -52,13 +52,18 @@ get_redirect_rule_by_index(int index,
int
delete_redirect_rule(const char * ifname, unsigned short eport, int proto);
/* delete_filter_rule()
/* delete_redirect_and_filter_rules()
*/
int
delete_filter_rule(const char * ifname, unsigned short eport, int proto);
delete_redirect_and_filter_rules(const char * ifname, unsigned short eport,
int proto);
#ifdef TEST
int
clear_redirect_rules(void);
int
clear_filter_rules(void);
#endif
#endif

View File

@ -1,10 +1,11 @@
/* $Id: testobsdrdr.c,v 1.24 2012/04/18 19:42:03 nanard Exp $ */
/* $Id: testobsdrdr.c,v 1.28 2014/03/06 13:02:47 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
@ -17,6 +18,7 @@
int runtime_flags = 0;
const char * tag = 0;
const char * anchor_name = "miniupnpd";
const char * queue = NULL;
void
list_rules(void);
@ -67,7 +69,7 @@ test_index(void)
}
int
main(int arc, char * * argv)
main(int argc, char * * argv)
{
char buf[32];
char desc[64];
@ -77,6 +79,12 @@ main(int arc, char * * argv)
unsigned int timestamp;
u_int64_t packets = 0;
u_int64_t bytes = 0;
int clear = 0;
if(argc > 1) {
if(0 == strcmp(argv[1], "--clear") || 0 == strcmp(argv[1], "-c"))
clear = 1;
}
openlog("testobsdrdr", LOG_PERROR, LOG_USER);
if(init_redirect() < 0)
@ -88,12 +96,15 @@ main(int arc, char * * argv)
add_redirect_rule("ep0", 12123, "192.168.1.23", 1234);
add_redirect_rule2("ep0", 12155, "192.168.1.155", 1255, IPPROTO_TCP);
#endif
add_redirect_rule2("ep0", "8.8.8.8", 12123, "192.168.1.125", 1234,
IPPROTO_UDP, "test description", 0);
#if 0
add_redirect_rule2("em0", 12123, "127.1.2.3", 1234,
IPPROTO_TCP, "test description tcp");
#endif
if(add_redirect_rule2("ep0", "8.8.8.8", 12123, "192.168.1.125", 1234,
IPPROTO_UDP, "test description", 0) < 0)
printf("add_redirect_rule2() #3 failed\n");
if(add_redirect_rule2("em0", NULL, 12123, "127.1.2.3", 1234,
IPPROTO_TCP, "test description tcp", 0) < 0)
printf("add_redirect_rule2() #4 failed\n");
if(add_filter_rule2("em0", NULL, "127.1.2.3", 12123, 1234, IPPROTO_TCP,
"test description tcp") < 0)
printf("add_filter_rule2() #1 failed\n");
list_rules();
list_eports_tcp();
@ -113,20 +124,20 @@ main(int arc, char * * argv)
if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0)
printf("delete_redirect_rule() failed\n");
else
printf("delete_redirect_rule() succeded\n");
if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0)
printf("delete_redirect_rule() failed\n");
else
printf("delete_redirect_rule() succeded\n");
#if 0
if(delete_redirect_and_filter_rules("em0", 12123, IPPROTO_TCP) < 0)
printf("delete_redirect_and_filter_rules() failed\n");
test_index();
if(clear) {
clear_redirect_rules();
list_rules();
#endif
clear_filter_rules();
}
/*list_rules();*/
return 0;
}

View File

@ -1,7 +1,7 @@
/* $Id: testpfpinhole.c,v 1.10 2012/04/22 23:12:51 nanard Exp $ */
/* $Id: testpfpinhole.c,v 1.11 2014/02/28 16:49:15 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2012 Thomas Bernard
* (c) 2012-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -21,6 +21,7 @@ const char * tag = NULL;
const char * anchor_name = "miniupnpd";
const char * queue = NULL;
#ifdef ENABLE_IPV6
static int print_pinhole(int uid)
{
int r;
@ -32,7 +33,7 @@ static int print_pinhole(int uid)
unsigned int timestamp;
u_int64_t packets, bytes;
r = get_pinhole((unsigned short)uid,
r = get_pinhole_info((unsigned short)uid,
rem_host, sizeof(rem_host), &rem_port,
int_client, sizeof(int_client), &int_port,
&proto, &timestamp,
@ -47,6 +48,7 @@ static int print_pinhole(int uid)
}
return r;
}
#endif
int main(int argc, char * *argv)
{

126
miniupnpd/testasyncsendto.c Normal file
View File

@ -0,0 +1,126 @@
/* $Id: testasyncsendto.c,v 1.2 2014/02/25 11:00:14 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <errno.h>
#include "miniupnpdtypes.h"
#include "upnputils.h"
#include "asyncsendto.h"
struct lan_addr_list lan_addrs;
#define DEST_IP "239.255.255.250"
#define DEST_PORT 1900
/*
ssize_t
sendto_schedule(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen,
unsigned int delay)
*/
int test(void)
{
int s;
ssize_t n;
int i;
struct sockaddr_in addr;
struct sockaddr_in dest_addr;
struct timeval next_send;
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
syslog(LOG_ERR, "socket(): %m");
return 1;
}
set_non_blocking(s);
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
syslog(LOG_ERR, "bind(): %m");
close(s);
return 1;
}
memset(&dest_addr, 0, sizeof(struct sockaddr_in));
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = inet_addr(DEST_IP);
dest_addr.sin_port = htons(DEST_PORT);
n = sendto_or_schedule(s, "1234", 4, 0,
(struct sockaddr *)&dest_addr, sizeof(dest_addr));
syslog(LOG_DEBUG, "sendto_or_schedule : %d", (int)n);
n = sendto_schedule(s, "1234", 4, 0,
(struct sockaddr *)&dest_addr, sizeof(dest_addr),
4400);
syslog(LOG_DEBUG, "sendto_schedule : %d", (int)n);
n = sendto_schedule(s, "1234", 4, 0,
(struct sockaddr *)&dest_addr, sizeof(dest_addr),
3000);
syslog(LOG_DEBUG, "sendto_schedule : %d", (int)n);
while ((i = get_next_scheduled_send(&next_send)) > 0) {
fd_set writefds;
int max_fd;
struct timeval timeout;
struct timeval now;
syslog(LOG_DEBUG, "get_next_scheduled_send : %d next_send=%ld.%06ld",
i, next_send.tv_sec, next_send.tv_usec);
FD_ZERO(&writefds);
max_fd = 0;
gettimeofday(&now, NULL);
i = get_sendto_fds(&writefds, &max_fd, &now);
if(now.tv_sec > next_send.tv_sec ||
(now.tv_sec == next_send.tv_sec && now.tv_usec >= next_send.tv_usec)) {
if(i > 0) {
/* dont wait */
timeout.tv_sec = 0;
} else {
/* wait 10sec :) */
timeout.tv_sec = 10;
}
timeout.tv_usec = 0;
} else {
/* ... */
timeout.tv_sec = (next_send.tv_sec - now.tv_sec);
timeout.tv_usec = (next_send.tv_usec - now.tv_usec);
if(timeout.tv_usec < 0) {
timeout.tv_usec += 1000000;
timeout.tv_sec--;
}
}
syslog(LOG_DEBUG, "get_sendto_fds() returned %d", i);
syslog(LOG_DEBUG, "select(%d, NULL, xx, NULL, %ld.%06ld)",
max_fd, timeout.tv_sec, timeout.tv_usec);
i = select(max_fd, NULL, &writefds, NULL, &timeout);
if(i < 0) {
syslog(LOG_ERR, "select: %m");
if(errno != EINTR)
break;
} else if(try_sendto(&writefds) < 0) {
syslog(LOG_ERR, "try_sendto: %m");
break;
}
}
close(s);
return 0;
}
int main(int argc, char * * argv)
{
int r;
(void)argc;
(void)argv;
openlog("testasyncsendto", LOG_CONS|LOG_PERROR, LOG_USER);
r = test();
closelog();
return r;
}

View File

@ -1,7 +1,7 @@
/* $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-2013 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdio.h>
@ -10,6 +10,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "config.h"
#include "getifaddr.h"
#if defined(__sun)
@ -21,6 +22,10 @@ int main(int argc, char * * argv) {
char str_addr[64];
struct in_addr addr;
struct in_addr mask;
#ifdef ENABLE_IPV6
int r;
char str_addr6[64];
#endif
if(argc < 2) {
fprintf(stderr, "Usage:\t%s interface_name\n", argv[0]);
return 1;
@ -34,5 +39,16 @@ int main(int argc, char * * argv) {
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));
#ifdef ENABLE_IPV6
r = find_ipv6_addr(argv[1], str_addr6, sizeof(str_addr6));
if(r < 0) {
fprintf(stderr, "find_ipv6_addr() failed\n");
return 1;
} else if(r == 0) {
printf("Interface %s has no IPv6 address.\n", argv[1]);
} else {
printf("Interface %s has IPv6 address %s.\n", argv[1], str_addr6);
}
#endif
return 0;
}

View File

@ -1,7 +1,7 @@
/* $Id: testupnpdescgen.c,v 1.30 2013/06/13 13:21:30 nanard Exp $ */
/* $Id: testupnpdescgen.c,v 1.32 2014/03/10 11:04:52 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -17,6 +17,7 @@
#include "config.h"
#include "upnpdescgen.h"
#include "upnpdescstrings.h"
#include "getifaddr.h"
char uuidvalue_igd[] = "uuid:12345678-0000-0000-0000-000000abcd01";
char uuidvalue_wan[] = "uuid:12345678-0000-0000-0000-000000abcd02";
@ -37,14 +38,13 @@ char model_url[] = ROOTDEV_MODELURL;
char * use_ext_ip_addr = NULL;
const char * ext_if_name = "eth0";
#ifdef ENABLE_6FC_SERVICE
int ipv6fc_firewall_enabled = 1;
int ipv6fc_inbound_pinhole_allowed = 1;
#endif
int runtime_flags = 0;
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;
}

View File

@ -1,7 +1,7 @@
/* $Id: upnpdescgen.c,v 1.74 2013/06/13 13:21:30 nanard Exp $ */
/* $Id: upnpdescgen.c,v 1.77 2014/03/10 11:04:53 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -1176,13 +1176,13 @@ genEventVars(int * len, const struct serviceDesc * s)
case FIREWALLENABLED_MAGICALVALUE:
/* see 2.4.2 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */
snprintf(tmp, sizeof(tmp), "%d",
ipv6fc_firewall_enabled);
GETFLAG(IPV6FCFWDISABLEDMASK) ? 0 : 1);
str = strcat_str(str, len, &tmplen, tmp);
break;
case INBOUNDPINHOLEALLOWED_MAGICALVALUE:
/* see 2.4.3 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */
snprintf(tmp, sizeof(tmp), "%d",
ipv6fc_inbound_pinhole_allowed);
GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK) ? 0 : 1);
str = strcat_str(str, len, &tmplen, tmp);
break;
#endif

View File

@ -1,4 +1,4 @@
/* $Id: upnpevents.c,v 1.27 2013/06/13 13:21:30 nanard Exp $ */
/* $Id: upnpevents.c,v 1.28 2014/03/13 10:53:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2008-2013 Thomas Bernard
@ -233,8 +233,10 @@ upnp_event_notify_connect(struct upnp_event_notify * obj)
unsigned short port;
#ifdef ENABLE_IPV6
struct sockaddr_storage addr;
socklen_t addrlen;
#else
struct sockaddr_in addr;
socklen_t addrlen;
#endif
if(!obj)
return;
@ -283,23 +285,28 @@ upnp_event_notify_connect(struct upnp_event_notify * obj)
sa->sin6_family = AF_INET6;
inet_pton(AF_INET6, obj->addrstr, &(sa->sin6_addr));
sa->sin6_port = htons(port);
addrlen = sizeof(struct sockaddr_in6);
} else {
struct sockaddr_in * sa = (struct sockaddr_in *)&addr;
sa->sin_family = AF_INET;
inet_pton(AF_INET, obj->addrstr, &(sa->sin_addr));
sa->sin_port = htons(port);
addrlen = sizeof(struct sockaddr_in);
}
#else
addr.sin_family = AF_INET;
inet_aton(obj->addrstr, &addr.sin_addr);
addr.sin_port = htons(port);
addrlen = sizeof(struct sockaddr_in);
#endif
syslog(LOG_DEBUG, "%s: '%s' %hu '%s'", "upnp_event_notify_connect",
obj->addrstr, port, obj->path);
obj->state = EConnecting;
if(connect(obj->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
if(connect(obj->s, (struct sockaddr *)&addr, addrlen) < 0) {
if(errno != EINPROGRESS && errno != EWOULDBLOCK) {
syslog(LOG_ERR, "%s: connect(): %m", "upnp_event_notify_connect");
syslog(LOG_ERR, "%s: connect(%d, %s, %u): %m",
"upnp_event_notify_connect", obj->s,
obj->addrstr, addrlen);
obj->state = EError;
}
}

View File

@ -1,7 +1,7 @@
/* $Id: upnpglobalvars.c,v 1.30 2013/06/13 13:21:30 nanard Exp $ */
/* $Id: upnpglobalvars.c,v 1.35 2014/03/10 11:04:53 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -24,17 +24,17 @@ const char* lease_file = 0;
* when NULL, getifaddr() is used */
const char * use_ext_ip_addr = 0;
/* LAN address */
/*const char * listen_addr = 0;*/
unsigned long downstream_bitrate = 0;
unsigned long upstream_bitrate = 0;
/* startup time */
time_t startup_time = 0;
#ifdef ENABLE_PCP
/* for PCP */
unsigned long int min_lifetime = 120;
unsigned long int max_lifetime = 86400;
#endif
int runtime_flags = 0;
@ -75,18 +75,10 @@ char model_url[MODEL_URL_MAX_LEN] = ROOTDEV_MODELURL;
struct upnpperm * upnppermlist = 0;
unsigned int num_upnpperm = 0;
#ifdef ENABLE_NATPMP
/* NAT-PMP */
#if 0
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
#endif /*PCP_SADSCP*/
/* For automatic removal of expired rules (with LeaseDuration) */
unsigned int nextruletoclean_timestamp = 0;
@ -127,8 +119,3 @@ const char * minissdpdsocketpath = "/var/run/minissdpd.sock";
unsigned int upnp_bootid = 1;
unsigned int upnp_configid = 1337;
#ifdef ENABLE_6FC_SERVICE
int ipv6fc_firewall_enabled = 1;
int ipv6fc_inbound_pinhole_allowed = 1;
#endif

View File

@ -1,7 +1,7 @@
/* $Id: upnpglobalvars.h,v 1.35 2013/06/13 13:21:30 nanard Exp $ */
/* $Id: upnpglobalvars.h,v 1.38 2014/03/10 11:04:53 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -51,6 +51,13 @@ extern int runtime_flags;
#ifdef PF_ENABLE_FILTER_RULES
#define PFNOQUICKRULESMASK 0x0040
#endif
#ifdef ENABLE_IPV6
#define IPV6DISABLEDMASK 0x0080
#endif
#ifdef ENABLE_6FC_SERVICE
#define IPV6FCFWDISABLEDMASK 0x0100
#define IPV6FCINBOUNDDISALLOWEDMASK 0x0200
#endif
#define SETFLAG(mask) runtime_flags |= mask
#define GETFLAG(mask) (runtime_flags & mask)
@ -95,18 +102,10 @@ extern char model_url[];
extern struct upnpperm * upnppermlist;
extern unsigned int num_upnpperm;
#ifdef ENABLE_NATPMP
/* NAT-PMP */
#if 0
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) */
extern unsigned int nextruletoclean_timestamp;
@ -147,10 +146,5 @@ extern const char * minissdpdsocketpath;
extern unsigned int upnp_bootid;
extern unsigned int upnp_configid;
#ifdef ENABLE_6FC_SERVICE
extern int ipv6fc_firewall_enabled;
extern int ipv6fc_inbound_pinhole_allowed;
#endif
#endif

View File

@ -1,7 +1,7 @@
/* $Id: upnppermissions.c,v 1.17 2012/02/15 22:43:34 nanard Exp $ */
/* $Id: upnppermissions.c,v 1.18 2014/03/07 10:43:29 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -223,6 +223,23 @@ match_permission(const struct upnpperm * perm,
return 1;
}
#if 0
/* match_permission_internal()
* returns: 1 if address, iport matches the permission rule
* 0 if no match */
static int
match_permission_internal(const struct upnpperm * perm,
struct in_addr address, u_short iport)
{
if( (iport < perm->iport_min) || (perm->iport_max < iport))
return 0;
if( (address.s_addr & perm->mask.s_addr)
!= (perm->address.s_addr & perm->mask.s_addr) )
return 0;
return 1;
}
#endif
int
check_upnp_rule_against_permissions(const struct upnpperm * permary,
int n_perms,

View File

@ -1,7 +1,7 @@
/* $Id: upnppermissions.h,v 1.7 2007/02/28 18:13:18 nanard Exp $ */
/* $Id: upnppermissions.h,v 1.10 2014/03/07 10:43:29 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */

View File

@ -1,7 +1,7 @@
/* $Id: upnpredirect.c,v 1.80 2012/05/01 20:08:22 nanard Exp $ */
/* $Id: upnpredirect.c,v 1.82 2014/02/28 20:18:35 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -424,6 +424,8 @@ _upnp_delete_redir(unsigned short eport, int proto)
int r;
#if defined(__linux__)
r = delete_redirect_and_filter_rules(eport, proto);
#elif defined(USE_PF)
r = delete_redirect_and_filter_rules(ext_if_name, eport, proto);
#else
r = delete_redirect_rule(ext_if_name, eport, proto);
delete_filter_rule(ext_if_name, eport, proto);

View File

@ -1,7 +1,7 @@
/* $Id: upnpsoap.c,v 1.119 2013/08/19 16:16:00 nanard Exp $ */
/* $Id: upnpsoap.c,v 1.122 2014/03/10 11:04:53 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -1220,19 +1220,21 @@ GetFirewallStatus(struct upnphttp * h, const char * action)
bodylen = snprintf(body, sizeof(body), resp,
action, "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1",
ipv6fc_firewall_enabled, ipv6fc_inbound_pinhole_allowed, action);
GETFLAG(IPV6FCFWDISABLEDMASK) ? 0 : 1,
GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK) ? 0 : 1,
action);
BuildSendAndCloseSoapResp(h, body, bodylen);
}
static int
CheckStatus(struct upnphttp * h)
{
if (!ipv6fc_firewall_enabled)
if (GETFLAG(IPV6FCFWDISABLEDMASK))
{
SoapError(h, 702, "FirewallDisabled");
return 0;
}
else if(!ipv6fc_inbound_pinhole_allowed)
else if(GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK))
{
SoapError(h, 703, "InboundPinholeNotAllowed");
return 0;
@ -1604,7 +1606,7 @@ GetOutboundPinholeTimeout(struct upnphttp * h, const char * action)
int opt=0, proto=0;
unsigned short iport, rport;
if (!ipv6fc_firewall_enabled)
if (GETFLAG(IPV6FCFWDISABLEDMASK))
{
SoapError(h, 702, "FirewallDisabled");
return;
@ -1910,6 +1912,10 @@ ExecuteSoapAction(struct upnphttp * h, const char * action, int n)
len = strlen(soapMethods[i].methodName);
if(strncmp(p, soapMethods[i].methodName, len) == 0)
{
#ifdef DEBUG
syslog(LOG_DEBUG, "Remote Call of SoapMethod '%s'\n",
soapMethods[i].methodName);
#endif
soapMethods[i].methodImpl(h, soapMethods[i].methodName);
return;
}

View File

@ -1,7 +1,7 @@
/* $Id: upnputils.c,v 1.7 2013/04/20 09:03:18 nanard Exp $ */
/* $Id: upnputils.c,v 1.8 2014/02/05 17:00:26 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2013 Thomas Bernard
* (c) 2006-2014 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -93,6 +93,7 @@ struct lan_addr_s *
get_lan_for_peer(const struct sockaddr * peer)
{
struct lan_addr_s * lan_addr = NULL;
char dbg_str[64];
#ifdef ENABLE_IPV6
if(peer->sa_family == AF_INET6)
@ -153,11 +154,15 @@ get_lan_for_peer(const struct sockaddr * peer)
}
#endif
if(lan_addr)
syslog(LOG_DEBUG, "%s: found in LAN %s %s",
"get_lan_for_peer()", lan_addr->ifname, lan_addr->str);
else
syslog(LOG_DEBUG, "%s: not found !", "get_lan_for_peer()");
sockaddr_to_string(peer, dbg_str, sizeof(dbg_str));
if(lan_addr) {
syslog(LOG_DEBUG, "%s: %s found in LAN %s %s",
"get_lan_for_peer()", dbg_str,
lan_addr->ifname, lan_addr->str);
} else {
syslog(LOG_DEBUG, "%s: %s not found !", "get_lan_for_peer()",
dbg_str);
}
return lan_addr;
}