AddPinhole() and DeletePinhole() works ! (only with pf)
This commit is contained in:
parent
82369d94e4
commit
e0efe74a7c
|
@ -1,4 +1,8 @@
|
||||||
$Id: Changelog.txt,v 1.271 2012/04/18 23:44:35 nanard Exp $
|
$Id: Changelog.txt,v 1.272 2012/04/20 14:38:38 nanard Exp $
|
||||||
|
|
||||||
|
2012/04/20:
|
||||||
|
Enough WANIPv6FirewallControl is implemented on pf so that AddPinhole() and
|
||||||
|
DeletePinhole() works !
|
||||||
|
|
||||||
2012/04/19:
|
2012/04/19:
|
||||||
First working experiment of IPv6 "pinhole" with pf
|
First working experiment of IPv6 "pinhole" with pf
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: upnpredirect.c,v 1.64 2012/04/14 22:12:09 nanard Exp $ */
|
/* $Id: upnpredirect.c,v 1.66 2012/04/20 14:38:38 nanard Exp $ */
|
||||||
/* MiniUPnP project
|
/* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||||
* (c) 2006-2012 Thomas Bernard
|
* (c) 2006-2012 Thomas Bernard
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_PF)
|
#if defined(USE_PF)
|
||||||
#include "pf/obsdrdr.h"
|
#include "pf/obsdrdr.h"
|
||||||
|
#include "pf/pfpinhole.h"
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_IPF)
|
#if defined(USE_IPF)
|
||||||
#include "ipf/ipfrdr.h"
|
#include "ipf/ipfrdr.h"
|
||||||
|
@ -626,6 +627,7 @@ upnp_check_outbound_pinhole(int proto, int * timeout)
|
||||||
* -1 failed to add pinhole
|
* -1 failed to add pinhole
|
||||||
* -2 already created
|
* -2 already created
|
||||||
* -3 inbound pinhole disabled
|
* -3 inbound pinhole disabled
|
||||||
|
* TODO : return uid on success (positive) or error value (negative)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
upnp_add_inboundpinhole(const char * raddr,
|
upnp_add_inboundpinhole(const char * raddr,
|
||||||
|
@ -633,33 +635,34 @@ upnp_add_inboundpinhole(const char * raddr,
|
||||||
const char * iaddr,
|
const char * iaddr,
|
||||||
unsigned short iport,
|
unsigned short iport,
|
||||||
const char * protocol,
|
const char * protocol,
|
||||||
const char * leaseTime,
|
unsigned int leasetime,
|
||||||
int * uid)
|
int * uid)
|
||||||
{
|
{
|
||||||
int r, s, t, lt=0;
|
int r;
|
||||||
char iaddr_old[40]="", proto[6]="", idfound[5]="", leaseTmp[12]; /* IPv6 Modification*/
|
|
||||||
snprintf(proto, sizeof(proto), "%.5d", atoi(protocol));
|
|
||||||
unsigned short iport_old = 0;
|
|
||||||
time_t current = time(NULL);
|
|
||||||
#if 0
|
#if 0
|
||||||
|
char iaddr_old[40]="", idfound[5]=""; /* IPv6 Modification*/
|
||||||
|
unsigned short iport_old = 0;
|
||||||
|
#endif
|
||||||
|
time_t current;
|
||||||
|
unsigned int timestamp;
|
||||||
struct in6_addr address; /* IPv6 Modification*/
|
struct in6_addr address; /* IPv6 Modification*/
|
||||||
|
int proto;
|
||||||
|
|
||||||
if(inet_pton(AF_INET6, iaddr, &address) < 0) /* IPv6 Modification */
|
if(inet_pton(AF_INET6, iaddr, &address) < 0) /* IPv6 Modification */
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "inet_pton(%s) : %m", iaddr);
|
syslog(LOG_ERR, "inet_pton(%s) : %m", iaddr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
proto = atoi(protocol); /* for WANIPv6FirewallControl AddPinhole, the protocol argument
|
||||||
|
* is passed as an integer, not a string */
|
||||||
|
current = time(NULL);
|
||||||
|
timestamp = current + leasetime;
|
||||||
#if 0
|
#if 0
|
||||||
r = get_rule_from_file(raddr, rport, iaddr_old, &iport_old, proto, 0, 0, idfound);
|
r = get_rule_from_file(raddr, rport, iaddr_old, &iport_old, proto, 0, 0, idfound);
|
||||||
#endif
|
#endif
|
||||||
r = 0;
|
r = 0;
|
||||||
|
|
||||||
lt = (int) current + atoi(leaseTime);
|
#if 0
|
||||||
snprintf(leaseTmp, sizeof(leaseTmp), "%d", lt);
|
|
||||||
printf("LeaseTime: %d / %d -> %s\n", atoi(leaseTime), (int)current, leaseTmp);
|
|
||||||
|
|
||||||
printf("\tCompare addr: %s // port: %d\n\t to addr: %s // port: %d\n", iaddr, iport, iaddr_old, iport_old);
|
|
||||||
if(r == 1 && strcmp(iaddr, iaddr_old)==0 && iport==iport_old)
|
if(r == 1 && strcmp(iaddr, iaddr_old)==0 && iport==iport_old)
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s already done. Updating it.", raddr, rport, iaddr_old, iport_old, protocol);
|
syslog(LOG_INFO, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s already done. Updating it.", raddr, rport, iaddr_old, iport_old, protocol);
|
||||||
|
@ -668,10 +671,17 @@ upnp_add_inboundpinhole(const char * raddr,
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "Adding pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s and %s lease time.", raddr, rport, iaddr, iport, protocol, leaseTime);
|
syslog(LOG_INFO, "Adding pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s and %u lease time.", raddr, rport, iaddr, iport, protocol, leasetime);
|
||||||
s = upnp_add_inboundpinhole_internal(raddr, rport, iaddr, iport, protocol, uid);
|
#ifdef USE_PF
|
||||||
|
*uid = add_pinhole (0/*ext_if_name*/, raddr, rport, iaddr, iport, proto, timestamp);
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return -42; /* not implemented */
|
||||||
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
|
s = upnp_add_inboundpinhole_internal(raddr, rport, iaddr, iport, protocol, uid);
|
||||||
if(rule_file_add(raddr, rport, iaddr, iport, protocol, leaseTmp, uid)<0)
|
if(rule_file_add(raddr, rport, iaddr, iport, protocol, leaseTmp, uid)<0)
|
||||||
return -8;
|
return -8;
|
||||||
else
|
else
|
||||||
|
@ -794,39 +804,15 @@ upnp_update_inboundpinhole(const char * uid, const char * leasetime)
|
||||||
int
|
int
|
||||||
upnp_delete_inboundpinhole(const char * uid)
|
upnp_delete_inboundpinhole(const char * uid)
|
||||||
{
|
{
|
||||||
/* TODO : to be implemented */
|
unsigned short uid_s;
|
||||||
#if 0
|
|
||||||
/* this is a alpha implementation calling ip6tables via system(),
|
if(!uid)
|
||||||
* it can be usefull as an example to code the netfilter version */
|
return -1;
|
||||||
int r, s, linenum=0;
|
uid_s = (unsigned short)atoi(uid);
|
||||||
char cmd[256], cmd_raw[256];
|
#ifdef USE_PF
|
||||||
syslog(LOG_INFO, "Removing pinhole for inbound traffic with ID: %s", uid);
|
return delete_pinhole(uid_s);
|
||||||
r = check_rule_from_file(uid, &linenum);
|
|
||||||
if(r > 0)
|
|
||||||
{
|
|
||||||
s = rule_file_remove(uid, linenum);
|
|
||||||
if(s < 0)
|
|
||||||
return s;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(cmd, sizeof(cmd), "ip6tables -t filter -D %s %d", miniupnpd_forward_chain, linenum);
|
|
||||||
snprintf(cmd_raw, sizeof(cmd_raw), "ip6tables -t raw -D PREROUTING %d", linenum -1);
|
|
||||||
#ifdef DEBUG
|
|
||||||
syslog(LOG_INFO, "Deleting ip6tables rule:");
|
|
||||||
syslog(LOG_INFO, " -> %s", cmd);
|
|
||||||
syslog(LOG_INFO, " -> %s", cmd_raw);
|
|
||||||
#endif
|
|
||||||
// TODO Add a better checking error.
|
|
||||||
if(system(cmd) < 0 || system(cmd_raw) < 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
upnp_update_expiredpinhole();
|
|
||||||
return r;
|
|
||||||
#else
|
#else
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: upnpsoap.c,v 1.93 2012/04/19 22:04:48 nanard Exp $ */
|
/* $Id: upnpsoap.c,v 1.96 2012/04/20 14:38:39 nanard Exp $ */
|
||||||
/* MiniUPnP project
|
/* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||||
* (c) 2006-2012 Thomas Bernard
|
* (c) 2006-2012 Thomas Bernard
|
||||||
|
@ -1259,8 +1259,6 @@ static int
|
||||||
PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short * int_port)
|
PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short * int_port)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
/* Pinhole InternalClient address must correspond to the action sender */
|
|
||||||
syslog(LOG_INFO, "Checking internal IP@ and port (Security policy purpose)");
|
|
||||||
char senderAddr[INET6_ADDRSTRLEN]="";
|
char senderAddr[INET6_ADDRSTRLEN]="";
|
||||||
#if 0
|
#if 0
|
||||||
//char str[INET6_ADDRSTRLEN]="";
|
//char str[INET6_ADDRSTRLEN]="";
|
||||||
|
@ -1271,6 +1269,9 @@ PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short * int_por
|
||||||
struct addrinfo hints, *ai, *p;
|
struct addrinfo hints, *ai, *p;
|
||||||
struct in6_addr result_ip;/*unsigned char result_ip[16];*/ /* inet_pton() */
|
struct in6_addr result_ip;/*unsigned char result_ip[16];*/ /* inet_pton() */
|
||||||
|
|
||||||
|
/* Pinhole InternalClient address must correspond to the action sender */
|
||||||
|
syslog(LOG_INFO, "Checking internal IP@ and port (Security policy purpose)");
|
||||||
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
|
||||||
|
@ -1341,6 +1342,7 @@ AddPinhole(struct upnphttp * h, const char * action)
|
||||||
char * rem_host, * rem_port, * int_ip, * int_port, * protocol, * leaseTime;
|
char * rem_host, * rem_port, * int_ip, * int_port, * protocol, * leaseTime;
|
||||||
int uid = 0;
|
int uid = 0;
|
||||||
unsigned short iport, rport;
|
unsigned short iport, rport;
|
||||||
|
int ltime;
|
||||||
|
|
||||||
if(CheckStatus(h)==0)
|
if(CheckStatus(h)==0)
|
||||||
return;
|
return;
|
||||||
|
@ -1353,9 +1355,17 @@ AddPinhole(struct upnphttp * h, const char * action)
|
||||||
protocol = GetValueFromNameValueList(&data, "Protocol");
|
protocol = GetValueFromNameValueList(&data, "Protocol");
|
||||||
leaseTime = GetValueFromNameValueList(&data, "LeaseTime");
|
leaseTime = GetValueFromNameValueList(&data, "LeaseTime");
|
||||||
|
|
||||||
rport = (unsigned short)atoi(rem_port);
|
rport = (unsigned short)(rem_port ? atoi(rem_port) : 0);
|
||||||
iport = (unsigned short)atoi(int_port);
|
iport = (unsigned short)(int_port ? atoi(int_port) : 0);
|
||||||
|
ltime = atoi(leaseTime);
|
||||||
|
|
||||||
|
/* In particular, [IGD2] RECOMMENDS that unauthenticated and
|
||||||
|
* unauthorized control points are only allowed to invoke
|
||||||
|
* this action with:
|
||||||
|
* - InternalPort value greater than or equal to 1024,
|
||||||
|
* - InternalClient value equals to the control point's IP address.
|
||||||
|
* It is REQUIRED that InternalClient cannot be one of IPv6
|
||||||
|
* addresses used by the gateway. */
|
||||||
/* ** As there is no security policy, InternalClient must be equal
|
/* ** As there is no security policy, InternalClient must be equal
|
||||||
* to the CP's IP address. */
|
* to the CP's IP address. */
|
||||||
if(DataVerification(h, int_ip, &iport, protocol, leaseTime) == 0
|
if(DataVerification(h, int_ip, &iport, protocol, leaseTime) == 0
|
||||||
|
@ -1377,7 +1387,11 @@ AddPinhole(struct upnphttp * h, const char * action)
|
||||||
|
|
||||||
syslog(LOG_INFO, "%s: (inbound) from [%s]:%hu to [%s]:%hu with protocol %s during %ssec", action, rem_host?rem_host:"anywhere", rport, int_ip, iport, protocol, leaseTime);
|
syslog(LOG_INFO, "%s: (inbound) from [%s]:%hu to [%s]:%hu with protocol %s during %ssec", action, rem_host?rem_host:"anywhere", rport, int_ip, iport, protocol, leaseTime);
|
||||||
|
|
||||||
r = upnp_add_inboundpinhole(rem_host, rport, int_ip, iport, protocol, leaseTime, &uid);
|
/* In cases where the RemoteHost, RemotePort, InternalPort,
|
||||||
|
* InternalClient and Protocol are the same than an existing pinhole,
|
||||||
|
* but LeaseTime is different, the device MUST extend the existing
|
||||||
|
* pinhole's lease time and return the UniqueID of the existing pinhole. */
|
||||||
|
r = upnp_add_inboundpinhole(rem_host, rport, int_ip, iport, protocol, ltime, &uid);
|
||||||
|
|
||||||
switch(r)
|
switch(r)
|
||||||
{
|
{
|
||||||
|
@ -1407,6 +1421,7 @@ UpdatePinhole(struct upnphttp * h, const char * action)
|
||||||
const char * uid, * leaseTime;
|
const char * uid, * leaseTime;
|
||||||
char iaddr[40], proto[6], lt[12];
|
char iaddr[40], proto[6], lt[12];
|
||||||
unsigned short iport;
|
unsigned short iport;
|
||||||
|
int ltime = -1;
|
||||||
|
|
||||||
if(CheckStatus(h)==0)
|
if(CheckStatus(h)==0)
|
||||||
return;
|
return;
|
||||||
|
@ -1414,8 +1429,10 @@ UpdatePinhole(struct upnphttp * h, const char * action)
|
||||||
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
||||||
uid = GetValueFromNameValueList(&data, "UniqueID");
|
uid = GetValueFromNameValueList(&data, "UniqueID");
|
||||||
leaseTime = GetValueFromNameValueList(&data, "NewLeaseTime");
|
leaseTime = GetValueFromNameValueList(&data, "NewLeaseTime");
|
||||||
|
if(leaseTime)
|
||||||
|
ltime = atoi(leaseTime);
|
||||||
|
|
||||||
if(!uid || !leaseTime || !atoi(leaseTime) || atoi(leaseTime) > 86400)
|
if(!uid || ltime <= 0 || ltime > 86400)
|
||||||
{
|
{
|
||||||
ClearNameValueList(&data);
|
ClearNameValueList(&data);
|
||||||
SoapError(h, 402, "Invalid Args");
|
SoapError(h, 402, "Invalid Args");
|
||||||
|
@ -1455,11 +1472,6 @@ UpdatePinhole(struct upnphttp * h, const char * action)
|
||||||
static void
|
static void
|
||||||
GetOutboundPinholeTimeout(struct upnphttp * h, const char * action)
|
GetOutboundPinholeTimeout(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
if (!ipv6fc_firewall_enabled)
|
|
||||||
{
|
|
||||||
SoapError(h, 702, "FirewallDisabed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
static const char resp[] =
|
static const char resp[] =
|
||||||
|
@ -1475,6 +1487,12 @@ GetOutboundPinholeTimeout(struct upnphttp * h, const char * action)
|
||||||
int opt=0, proto=0;
|
int opt=0, proto=0;
|
||||||
unsigned short iport, rport;
|
unsigned short iport, rport;
|
||||||
|
|
||||||
|
if (!ipv6fc_firewall_enabled)
|
||||||
|
{
|
||||||
|
SoapError(h, 702, "FirewallDisabed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
||||||
int_ip = GetValueFromNameValueList(&data, "InternalClient");
|
int_ip = GetValueFromNameValueList(&data, "InternalClient");
|
||||||
int_port = GetValueFromNameValueList(&data, "InternalPort");
|
int_port = GetValueFromNameValueList(&data, "InternalPort");
|
||||||
|
@ -1508,8 +1526,6 @@ GetOutboundPinholeTimeout(struct upnphttp * h, const char * action)
|
||||||
static void
|
static void
|
||||||
DeletePinhole(struct upnphttp * h, const char * action)
|
DeletePinhole(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
if(CheckStatus(h)==0)
|
|
||||||
return;
|
|
||||||
int r, n;
|
int r, n;
|
||||||
|
|
||||||
static const char resp[] =
|
static const char resp[] =
|
||||||
|
@ -1522,10 +1538,13 @@ DeletePinhole(struct upnphttp * h, const char * action)
|
||||||
char iaddr[40], proto[6], lt[12];
|
char iaddr[40], proto[6], lt[12];
|
||||||
unsigned short iport;
|
unsigned short iport;
|
||||||
|
|
||||||
|
if(CheckStatus(h)==0)
|
||||||
|
return;
|
||||||
|
|
||||||
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
||||||
uid = GetValueFromNameValueList(&data, "UniqueID");
|
uid = GetValueFromNameValueList(&data, "UniqueID");
|
||||||
|
|
||||||
if(!uid)
|
if(!uid || atoi(uid) < 0 || atoi(uid) > 65535)
|
||||||
{
|
{
|
||||||
ClearNameValueList(&data);
|
ClearNameValueList(&data);
|
||||||
SoapError(h, 402, "Invalid Args");
|
SoapError(h, 402, "Invalid Args");
|
||||||
|
@ -1548,7 +1567,7 @@ DeletePinhole(struct upnphttp * h, const char * action)
|
||||||
|
|
||||||
r = upnp_delete_inboundpinhole(uid);
|
r = upnp_delete_inboundpinhole(uid);
|
||||||
|
|
||||||
if(r <= 0)
|
if(r < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "%s: (inbound) failed to remove pinhole with ID: %s", action, uid);
|
syslog(LOG_INFO, "%s: (inbound) failed to remove pinhole with ID: %s", action, uid);
|
||||||
if(r==-4)
|
if(r==-4)
|
||||||
|
@ -1567,8 +1586,6 @@ DeletePinhole(struct upnphttp * h, const char * action)
|
||||||
static void
|
static void
|
||||||
CheckPinholeWorking(struct upnphttp * h, const char * action)
|
CheckPinholeWorking(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
if(CheckStatus(h)==0)
|
|
||||||
return;
|
|
||||||
int r, d;
|
int r, d;
|
||||||
|
|
||||||
static const char resp[] =
|
static const char resp[] =
|
||||||
|
@ -1585,6 +1602,9 @@ CheckPinholeWorking(struct upnphttp * h, const char * action)
|
||||||
unsigned short eport, iport;
|
unsigned short eport, iport;
|
||||||
int isWorking = 0;
|
int isWorking = 0;
|
||||||
|
|
||||||
|
if(CheckStatus(h)==0)
|
||||||
|
return;
|
||||||
|
|
||||||
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
||||||
uid = GetValueFromNameValueList(&data, "UniqueID");
|
uid = GetValueFromNameValueList(&data, "UniqueID");
|
||||||
|
|
||||||
|
@ -1665,8 +1685,6 @@ CheckPinholeWorking(struct upnphttp * h, const char * action)
|
||||||
static void
|
static void
|
||||||
GetPinholePackets(struct upnphttp * h, const char * action)
|
GetPinholePackets(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
if(CheckStatus(h)==0)
|
|
||||||
return;
|
|
||||||
int r, n;
|
int r, n;
|
||||||
|
|
||||||
static const char resp[] =
|
static const char resp[] =
|
||||||
|
@ -1683,6 +1701,9 @@ GetPinholePackets(struct upnphttp * h, const char * action)
|
||||||
unsigned short iport;
|
unsigned short iport;
|
||||||
int pinholePackets = 0;
|
int pinholePackets = 0;
|
||||||
|
|
||||||
|
if(CheckStatus(h)==0)
|
||||||
|
return;
|
||||||
|
|
||||||
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data);
|
||||||
uid = GetValueFromNameValueList(&data, "UniqueID");
|
uid = GetValueFromNameValueList(&data, "UniqueID");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue