Merge remote branch 'origin/master' into portinuse
Conflicts: miniupnpd/Makefile.linux miniupnpd/natpmp.c
This commit is contained in:
commit
06764123fb
4
README
4
README
|
@ -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
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
minissdpd
|
||||
testcodelength
|
||||
testminissdpd
|
||||
listifaces
|
||||
Makefile.bak
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,20 +32,28 @@ 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;
|
||||
buf = realloc(buf, buflen);
|
||||
#endif
|
||||
if(buflen > 0)
|
||||
buf = realloc(buf, buflen);
|
||||
ifc.ifc_len = buflen;
|
||||
ifc.ifc_buf = (caddr_t)buf;
|
||||
if(ioctl(s, SIOCGIFCONF, &ifc) < 0)
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,7 +1070,10 @@ int main(int argc, char * * argv)
|
|||
(struct sockaddr *)&sendername6, &sendername6_len);
|
||||
if(n<0)
|
||||
{
|
||||
syslog(LOG_ERR, "recvfrom: %m");
|
||||
/* 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,7 +1104,10 @@ int main(int argc, char * * argv)
|
|||
(struct sockaddr *)&sendername, &sendername_len);
|
||||
if(n<0)
|
||||
{
|
||||
syslog(LOG_ERR, "recvfrom: %m");
|
||||
/* 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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.8
|
||||
1.9
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
LIBRARY
|
||||
; miniupnpc library
|
||||
miniupnpc
|
||||
|
||||
EXPORTS
|
||||
; miniupnpc
|
||||
|
|
|
@ -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" {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
NewProtocol=UDP
|
||||
NewExternalPort=12345
|
||||
NewRemoteHost=
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
NewInternalPort=12345
|
||||
NewInternalClient=192.168.10.110
|
||||
NewEnabled=1
|
||||
NewPortMappingDescription=libminiupnpc
|
||||
NewLeaseDuration=0
|
|
@ -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>
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
@ -578,7 +578,8 @@ LIBSPEC int
|
|||
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
|
||||
const char * servicetype,
|
||||
const char * extPort,
|
||||
const char * proto,
|
||||
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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -9,3 +9,7 @@ testgetifstats
|
|||
testupnpdescgen
|
||||
testupnppermissions
|
||||
testgetroute
|
||||
testasyncsendto
|
||||
netfilter/testiptcrdr
|
||||
netfilter/testiptcrdr_dscp
|
||||
netfilter/testiptcrdr_peer
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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,
|
||||
|
|
|
@ -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}
|
||||
FW=ipfw
|
||||
# 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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
sockets[i] = OpenAndConfSSDPNotifySocketIPv6(lan_addr->index);
|
||||
if(sockets[i] < 0)
|
||||
goto error;
|
||||
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
|
||||
SendSSDPNotifies(sockets[i], ipv6_addr_for_http_with_brackets, port,
|
||||
lifetime, 1);
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
listenname_len = sizeof(struct sockaddr_in6);
|
||||
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,10 +1594,13 @@ main(int argc, char * * argv)
|
|||
}
|
||||
}
|
||||
#ifdef ENABLE_IPV6
|
||||
sudpv6 = OpenAndConfSSDPReceiveSocket(1);
|
||||
if(sudpv6 < 0)
|
||||
if(!GETFLAG(IPV6DISABLEDMASK))
|
||||
{
|
||||
syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
|
||||
sudpv6 = OpenAndConfSSDPReceiveSocket(1);
|
||||
if(sudpv6 < 0)
|
||||
{
|
||||
syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6).");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -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)
|
||||
struct upnphttp * tmp;
|
||||
tmp = ProcessIncomingHTTP(shttpl);
|
||||
if(tmp)
|
||||
{
|
||||
/* 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
|
||||
LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_ERR, "New_upnphttp() failed");
|
||||
close(shttp);
|
||||
}
|
||||
}
|
||||
LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
|
||||
}
|
||||
}
|
||||
#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
|
||||
if(shttpl_v4 >= 0 && FD_ISSET(shttpl_v4, &readset))
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,38 +265,61 @@ 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 {
|
||||
r = get_redirect_rule(ext_if_name, eport, proto,
|
||||
iaddr_old, sizeof(iaddr_old),
|
||||
&iport_old, 0, 0, 0, 0,
|
||||
×tamp, 0, 0);
|
||||
if(r==0) {
|
||||
if(strcmp(senderaddrstr, iaddr_old)==0
|
||||
&& iport==iport_old) {
|
||||
/* redirection allready existing */
|
||||
syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing",
|
||||
eport, (proto==IPPROTO_TCP)?"tcp":"udp", iaddr_old, iport_old);
|
||||
/* remove and then add again */
|
||||
if(_upnp_delete_redir(eport, proto) < 0) {
|
||||
syslog(LOG_ERR, "failed to remove port mapping");
|
||||
break;
|
||||
} 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 */
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) {
|
||||
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];
|
||||
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,
|
||||
×tamp, 0, 0);
|
||||
if(r==0) {
|
||||
if(strcmp(senderaddrstr, iaddr_old)==0
|
||||
&& iport==iport_old) {
|
||||
/* redirection allready existing */
|
||||
syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing",
|
||||
eport, (proto==IPPROTO_TCP)?"tcp":"udp", iaddr_old, iport_old);
|
||||
/* remove and then add again */
|
||||
if(_upnp_delete_redir(eport, proto) < 0) {
|
||||
syslog(LOG_ERR, "failed to remove port mapping");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
eport++;
|
||||
if(eport == 0) eport++; /* skip port zero */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* 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),
|
||||
×tamp, 0, 0);
|
||||
if(r<0)
|
||||
break;
|
||||
if(sscanf(desc, "NAT-PMP %u", ×tamp) == 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), ×tamp, 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", ×tamp) == 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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
} 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);
|
||||
|
||||
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)))) {
|
||||
pcp_msg_info->result_code = PCP_ERR_CANNOT_PROVIDE_EXTERNAL;
|
||||
return;
|
||||
}
|
||||
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");
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
clear_redirect_rules();
|
||||
list_rules();
|
||||
#endif
|
||||
if(clear) {
|
||||
clear_redirect_rules();
|
||||
clear_filter_rules();
|
||||
}
|
||||
/*list_rules();*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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,11 +33,11 @@ static int print_pinhole(int uid)
|
|||
unsigned int timestamp;
|
||||
u_int64_t packets, bytes;
|
||||
|
||||
r = get_pinhole((unsigned short)uid,
|
||||
rem_host, sizeof(rem_host), &rem_port,
|
||||
int_client, sizeof(int_client), &int_port,
|
||||
&proto, ×tamp,
|
||||
&packets, &bytes);
|
||||
r = get_pinhole_info((unsigned short)uid,
|
||||
rem_host, sizeof(rem_host), &rem_port,
|
||||
int_client, sizeof(int_client), &int_port,
|
||||
&proto, ×tamp,
|
||||
&packets, &bytes);
|
||||
if(r < 0) {
|
||||
fprintf(stderr, "get_pinhole(%d) returned %d\n", uid, r);
|
||||
} else {
|
||||
|
@ -47,6 +48,7 @@ static int print_pinhole(int uid)
|
|||
}
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char * *argv)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue