Merge branch 'fix_pf_redirect'
Conflicts: miniupnpd/pf/testobsdrdr.c
This commit is contained in:
commit
a27979afde
|
@ -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
|
||||
*
|
||||
*
|
||||
*
|
||||
|
@ -176,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() :
|
||||
|
@ -347,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;
|
||||
|
@ -372,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;
|
||||
|
@ -407,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)
|
||||
{
|
||||
|
@ -450,9 +478,6 @@ add_filter_rule2(const char * ifname,
|
|||
}
|
||||
}
|
||||
}
|
||||
#ifndef PF_NEWSTYLE
|
||||
free(a);
|
||||
#endif
|
||||
}
|
||||
return r;
|
||||
#endif
|
||||
|
@ -575,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;
|
||||
|
@ -614,6 +641,44 @@ delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
|
|||
#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)
|
||||
{
|
||||
|
@ -636,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;
|
||||
|
@ -665,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)
|
||||
|
@ -689,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,
|
||||
|
|
|
@ -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.26 2014/02/28 18:03:31 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-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>
|
||||
|
@ -68,7 +69,7 @@ test_index(void)
|
|||
}
|
||||
|
||||
int
|
||||
main(int arc, char * * argv)
|
||||
main(int argc, char * * argv)
|
||||
{
|
||||
char buf[32];
|
||||
char desc[64];
|
||||
|
@ -78,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)
|
||||
|
@ -89,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);
|
||||
add_redirect_rule2("em0", NULL, 12123, "127.1.2.3", 1234,
|
||||
IPPROTO_TCP, "test description tcp", 0);
|
||||
add_filter_rule2("em0", NULL, "127.1.2.3", 12123, 1234, IPPROTO_TCP,
|
||||
"test description tcp");
|
||||
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();
|
||||
|
@ -114,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: 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 */
|
||||
|
||||
|
@ -419,6 +419,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);
|
||||
|
|
Loading…
Reference in New Issue