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
|
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||||
* MiniUPnP project
|
* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
|
||||||
|
@ -67,6 +67,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "obsdrdr.h"
|
#include "obsdrdr.h"
|
||||||
#include "../upnpglobalvars.h"
|
#include "../upnpglobalvars.h"
|
||||||
|
#include "../getifaddr.h"
|
||||||
|
|
||||||
#ifndef USE_PF
|
#ifndef USE_PF
|
||||||
#error "USE_PF macro is undefined, check consistency between config.h and Makefile"
|
#error "USE_PF macro is undefined, check consistency between config.h and Makefile"
|
||||||
|
@ -246,6 +247,168 @@ error:
|
||||||
}
|
}
|
||||||
#endif
|
#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() :
|
/* add_redirect_rule2() :
|
||||||
* create a rdr rule */
|
* create a rdr rule */
|
||||||
int
|
int
|
||||||
|
@ -260,6 +423,7 @@ add_redirect_rule2(const char * ifname,
|
||||||
struct pfioc_pooladdr pp;
|
struct pfioc_pooladdr pp;
|
||||||
struct pf_pooladdr *a;
|
struct pf_pooladdr *a;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(dev<0) {
|
if(dev<0) {
|
||||||
syslog(LOG_ERR, "pf device is not open");
|
syslog(LOG_ERR, "pf device is not open");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -407,6 +571,13 @@ add_redirect_rule2(const char * ifname,
|
||||||
}
|
}
|
||||||
if(r == 0 && timestamp > 0)
|
if(r == 0 && timestamp > 0)
|
||||||
add_timestamp_entry(eport, proto, timestamp);
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue