miniupnpd/pf: add_nat_rule()
This commit is contained in:
parent
abefb6c6d0
commit
2cf50c57fa
|
@ -1,4 +1,4 @@
|
|||
/* $Id: obsdrdr.c,v 1.95 2020/05/17 20:22:01 nanard Exp $ */
|
||||
/* $Id: obsdrdr.c,v 1.96 2020/05/21 00:18:04 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||
|
@ -67,6 +67,7 @@
|
|||
#include "config.h"
|
||||
#include "obsdrdr.h"
|
||||
#include "../upnpglobalvars.h"
|
||||
#include "../getifaddr.h"
|
||||
|
||||
#ifndef USE_PF
|
||||
#error "USE_PF macro is undefined, check consistency between config.h and Makefile"
|
||||
|
@ -246,6 +247,168 @@ error:
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_PORT_TRIGGERING
|
||||
/* add_nat_rule()
|
||||
* nat on re0 inet proto udp from 192.168.1.49 port 3074 to any -> (re0) port 3148
|
||||
* <re0> is ext_if, (re0) is ext_ip
|
||||
* should be created when a port mapping (3148 => 192.168.1.49:3074 UDP) is created.
|
||||
* for symetric NAT / UPnP IGD NAT Port Triggering */
|
||||
int add_nat_rule(const char * ifname,
|
||||
const char * rhost, unsigned short eport,
|
||||
const char * iaddr, unsigned short iport, int proto,
|
||||
const char * desc)
|
||||
{
|
||||
int r;
|
||||
struct pfioc_rule pcr;
|
||||
#ifndef PF_NEWSTYLE
|
||||
struct pfioc_pooladdr pp;
|
||||
struct pf_pooladdr *a;
|
||||
#endif
|
||||
const char * extaddr;
|
||||
char extaddr_buf[INET_ADDRSTRLEN];
|
||||
|
||||
if(dev<0) {
|
||||
syslog(LOG_ERR, "pf device is not open");
|
||||
return -1;
|
||||
}
|
||||
if(use_ext_ip_addr && use_ext_ip_addr[0] != '\0') {
|
||||
extaddr = use_ext_ip_addr;
|
||||
} else {
|
||||
if(getifaddr(ifname, extaddr_buf, INET_ADDRSTRLEN, NULL, NULL) < 0) {
|
||||
syslog(LOG_WARNING, "failed to get address for interface %s", ifname);
|
||||
return -1;
|
||||
}
|
||||
extaddr = extaddr_buf;
|
||||
}
|
||||
syslog(LOG_DEBUG, "use external ip %s", extaddr);
|
||||
r = 0;
|
||||
memset(&pcr, 0, sizeof(pcr));
|
||||
strlcpy(pcr.anchor, anchor_name, MAXPATHLEN);
|
||||
|
||||
#ifndef PF_NEWSTYLE
|
||||
memset(&pp, 0, sizeof(pp));
|
||||
strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
|
||||
if(ioctl(dev, DIOCBEGINADDRS, &pp) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ioctl(dev, DIOCBEGINADDRS, ...): %m");
|
||||
r = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcr.pool_ticket = pp.ticket;
|
||||
#else
|
||||
{
|
||||
pcr.rule.nat.addr.type = PF_ADDR_ADDRMASK;
|
||||
pcr.rule.rdr.addr.type = PF_ADDR_NONE;
|
||||
#endif
|
||||
/*pcr.rule.src.addr.type = PF_ADDR_NONE;*/
|
||||
pcr.rule.src.addr.type = PF_ADDR_ADDRMASK;
|
||||
pcr.rule.dst.addr.type = PF_ADDR_ADDRMASK;
|
||||
|
||||
pcr.rule.action = PF_NAT;
|
||||
pcr.rule.af = AF_INET;
|
||||
#ifdef USE_IFNAME_IN_RULES
|
||||
if(ifname)
|
||||
strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ);
|
||||
#endif
|
||||
pcr.rule.proto = proto;
|
||||
pcr.rule.log = (GETFLAG(LOGPACKETSMASK))?1:0; /*logpackets;*/
|
||||
#ifdef PFRULE_HAS_RTABLEID
|
||||
pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */
|
||||
#endif
|
||||
#ifdef PFRULE_HAS_ONRDOMAIN
|
||||
pcr.rule.onrdomain = -1; /* first appeared in OpenBSD 5.0 */
|
||||
#endif
|
||||
pcr.rule.quick = 1;
|
||||
pcr.rule.keep_state = PF_STATE_NORMAL;
|
||||
if(tag)
|
||||
strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE);
|
||||
strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
|
||||
#ifdef PFVAR_NEW_STYLE
|
||||
inet_pton(AF_INET, iaddr, &pcr.rule.src.addr.v.a.addr.v4addr.s_addr);
|
||||
pcr.rule.src.addr.v.a.mask.v4addr.s_addr = htonl(INADDR_NONE);
|
||||
#else
|
||||
inet_pton(AF_INET, iaddr, &pcr.rule.src.addr.v.a.addr.v4.s_addr);
|
||||
pcr.rule.src.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
pcr.rule.src.xport.range.op = PF_OP_EQ;
|
||||
pcr.rule.src.xport.range.port[0] = htons(iport);
|
||||
pcr.rule.src.xport.range.port[1] = htons(iport);
|
||||
#else
|
||||
pcr.rule.src.port_op = PF_OP_EQ;
|
||||
pcr.rule.src.port[0] = htons(iport);
|
||||
pcr.rule.src.port[1] = htons(iport);
|
||||
#endif
|
||||
if(rhost && rhost[0] != '\0' && rhost[0] != '*')
|
||||
{
|
||||
#ifdef PFVAR_NEW_STYLE
|
||||
inet_pton(AF_INET, rhost, &pcr.rule.dst.addr.v.a.addr.v4addr.s_addr);
|
||||
pcr.rule.dst.addr.v.a.mask.v4addr.s_addr = htonl(INADDR_NONE);
|
||||
#else
|
||||
inet_pton(AF_INET, rhost, &pcr.rule.dst.addr.v.a.addr.v4.s_addr);
|
||||
pcr.rule.dst.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
|
||||
#endif
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
pcr.rule.dst.xport.range.op = PF_OP_NONE;
|
||||
#else
|
||||
pcr.rule.dst.port_op = PF_OP_NONE;
|
||||
#endif
|
||||
/* -> xxx.xxx.xxx.xxx port 1234 */
|
||||
#ifndef PF_NEWSTYLE
|
||||
pcr.rule.rpool.proxy_port[0] = eport;
|
||||
pcr.rule.rpool.proxy_port[1] = eport;
|
||||
TAILQ_INIT(&pcr.rule.rpool.list);
|
||||
a = calloc(1, sizeof(struct pf_pooladdr));
|
||||
#ifdef PFVAR_NEW_STYLE
|
||||
inet_pton(AF_INET, extaddr, &a->addr.v.a.addr.v4addr.s_addr);
|
||||
a->addr.v.a.mask.v4addr.s_addr = htonl(INADDR_NONE);
|
||||
#else
|
||||
inet_pton(AF_INET, extaddr, &a->addr.v.a.addr.v4.s_addr);
|
||||
a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
|
||||
#endif
|
||||
TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries);
|
||||
|
||||
memcpy(&pp.addr, a, sizeof(struct pf_pooladdr));
|
||||
if(ioctl(dev, DIOCADDADDR, &pp) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ioctl(dev, DIOCADDADDR, ...): %m");
|
||||
r = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#else
|
||||
pcr.rule.nat.proxy_port[0] = eport;
|
||||
pcr.rule.nat.proxy_port[1] = eport;
|
||||
inet_pton(AF_INET, extaddr, &pcr.rule.nat.addr.v.a.addr.v4.s_addr);
|
||||
pcr.rule.nat.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
|
||||
{
|
||||
#endif /* PF_NEWSTYLE */
|
||||
pcr.action = PF_CHANGE_GET_TICKET;
|
||||
if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
|
||||
r = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcr.action = PF_CHANGE_ADD_TAIL;
|
||||
if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m");
|
||||
r = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef PF_NEWSTYLE
|
||||
free(a);
|
||||
#endif
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* add_redirect_rule2() :
|
||||
* create a rdr rule */
|
||||
int
|
||||
|
@ -260,6 +423,7 @@ add_redirect_rule2(const char * ifname,
|
|||
struct pfioc_pooladdr pp;
|
||||
struct pf_pooladdr *a;
|
||||
#endif
|
||||
|
||||
if(dev<0) {
|
||||
syslog(LOG_ERR, "pf device is not open");
|
||||
return -1;
|
||||
|
@ -407,6 +571,13 @@ add_redirect_rule2(const char * ifname,
|
|||
}
|
||||
if(r == 0 && timestamp > 0)
|
||||
add_timestamp_entry(eport, proto, timestamp);
|
||||
#ifdef ENABLE_PORT_TRIGGERING
|
||||
if(r == 0 && proto == IPPROTO_UDP)
|
||||
{
|
||||
add_nat_rule(ifname, rhost, eport, iaddr, iport, proto, desc);
|
||||
/* TODO check error */
|
||||
}
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue