rework nft-specific globals, create & destroy tables/chains at init & shutdown
This commit is contained in:
parent
d5773600f9
commit
75bdb777cf
|
@ -41,11 +41,10 @@ MANINSTALLDIR = $(INSTALLPREFIX)/share/man/man8
|
||||||
|
|
||||||
BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
|
BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
|
||||||
upnpreplyparse.o minixml.o portinuse.o \
|
upnpreplyparse.o minixml.o portinuse.o \
|
||||||
upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \
|
upnpredirect.o getifaddr.o daemonize.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 \
|
upnpglobalvars.o upnpevents.o upnputils.o getconnstatus.o \
|
||||||
upnpstun.o \
|
upnpstun.o upnppinhole.o pcplearndscp.o asyncsendto.o
|
||||||
upnppinhole.o pcplearndscp.o asyncsendto.o
|
|
||||||
|
|
||||||
LNXOBJS = linux/getifstats.o linux/ifacewatcher.o linux/getroute.o
|
LNXOBJS = linux/getifstats.o linux/ifacewatcher.o linux/getroute.o
|
||||||
NETFILTEROBJS = netfilter_nft/nftnlrdr.o netfilter_nft/nftpinhole.o \
|
NETFILTEROBJS = netfilter_nft/nftnlrdr.o netfilter_nft/nftpinhole.o \
|
||||||
|
@ -233,9 +232,9 @@ linux/ifacewatcher.o: miniupnpdtypes.h getifaddr.h upnpglobalvars.h
|
||||||
linux/ifacewatcher.o: upnppermissions.h natpmp.h
|
linux/ifacewatcher.o: upnppermissions.h natpmp.h
|
||||||
linux/getroute.o: getroute.h upnputils.h
|
linux/getroute.o: getroute.h upnputils.h
|
||||||
netfilter_nft/nftnlrdr.o: macros.h config.h netfilter_nft/nftnlrdr.h commonrdr.h
|
netfilter_nft/nftnlrdr.o: macros.h config.h netfilter_nft/nftnlrdr.h commonrdr.h
|
||||||
netfilter_nft/nftnlrdr.o: config.h upnpglobalvars.h upnppermissions.h
|
netfilter_nft/nftnlrdr.o: config.h upnppermissions.h
|
||||||
netfilter_nft/nftnlrdr.o: miniupnpdtypes.h
|
netfilter_nft/nftnlrdr.o: miniupnpdtypes.h
|
||||||
netfilter_nft/nftpinhole.o: config.h netfilter_nft/nftpinhole.h upnpglobalvars.h
|
netfilter_nft/nftpinhole.o: config.h netfilter_nft/nftpinhole.h
|
||||||
netfilter_nft/nftpinhole.o: upnppermissions.h config.h miniupnpdtypes.h
|
netfilter_nft/nftpinhole.o: upnppermissions.h config.h miniupnpdtypes.h
|
||||||
testupnpdescgen.o: macros.h config.h upnpdescgen.h upnpdescstrings.h
|
testupnpdescgen.o: macros.h config.h upnpdescgen.h upnpdescstrings.h
|
||||||
testupnpdescgen.o: getifaddr.h
|
testupnpdescgen.o: getifaddr.h
|
||||||
|
|
|
@ -64,4 +64,20 @@ update_portmapping_desc_timestamp(const char * ifname,
|
||||||
unsigned short eport, int proto,
|
unsigned short eport, int proto,
|
||||||
const char * desc, unsigned int timestamp);
|
const char * desc, unsigned int timestamp);
|
||||||
|
|
||||||
|
#ifdef USE_NFTABLES
|
||||||
|
/* only provided by nftables implementation at the moment */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TABLE_NAME,
|
||||||
|
TABLE4_NAME,
|
||||||
|
TABLE6_NAME,
|
||||||
|
NAT_CHAIN_NAME,
|
||||||
|
NAT_POSTROUTING_CHAIN_NAME,
|
||||||
|
FORWARD_CHAIN_NAME,
|
||||||
|
} rdr_name_type;
|
||||||
|
|
||||||
|
int set_rdr_name( rdr_name_type param, const char * string );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1267,6 +1267,17 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
||||||
break;
|
break;
|
||||||
#endif /* ENABLE_MANUFACTURER_INFO_CONFIGURATION */
|
#endif /* ENABLE_MANUFACTURER_INFO_CONFIGURATION */
|
||||||
#ifdef USE_NETFILTER
|
#ifdef USE_NETFILTER
|
||||||
|
#ifdef USE_NFTABLES
|
||||||
|
case UPNPFORWARDCHAIN:
|
||||||
|
set_rdr_name(FORWARD_CHAIN_NAME, ary_options[i].value);
|
||||||
|
break;
|
||||||
|
case UPNPNATCHAIN:
|
||||||
|
set_rdr_name(NAT_CHAIN_NAME, ary_options[i].value);
|
||||||
|
break;
|
||||||
|
case UPNPNATPOSTCHAIN:
|
||||||
|
set_rdr_name(NAT_POSTROUTING_CHAIN_NAME, ary_options[i].value);
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case UPNPFORWARDCHAIN:
|
case UPNPFORWARDCHAIN:
|
||||||
miniupnpd_forward_chain = ary_options[i].value;
|
miniupnpd_forward_chain = ary_options[i].value;
|
||||||
break;
|
break;
|
||||||
|
@ -1276,7 +1287,8 @@ init(int argc, char * * argv, struct runtime_vars * v)
|
||||||
case UPNPNATPOSTCHAIN:
|
case UPNPNATPOSTCHAIN:
|
||||||
miniupnpd_nat_postrouting_chain = ary_options[i].value;
|
miniupnpd_nat_postrouting_chain = ary_options[i].value;
|
||||||
break;
|
break;
|
||||||
#endif /* USE_NETFILTER */
|
#endif /* else USE_NFTABLES */
|
||||||
|
#endif /* USE_NETFILTER */
|
||||||
case UPNPNOTIFY_INTERVAL:
|
case UPNPNOTIFY_INTERVAL:
|
||||||
v->notify_interval = atoi(ary_options[i].value);
|
v->notify_interval = atoi(ary_options[i].value);
|
||||||
break;
|
break;
|
||||||
|
@ -2901,6 +2913,8 @@ shutdown:
|
||||||
freeoptions();
|
freeoptions();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
shutdown_redirect();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ clean:
|
||||||
$(RM) *.o testnftnlcrdr testnftpinhole testnftnlrdr_peer \
|
$(RM) *.o testnftnlcrdr testnftpinhole testnftnlrdr_peer \
|
||||||
test_nfct_get testnftnlrdr
|
test_nfct_get testnftnlrdr
|
||||||
|
|
||||||
testnftnlrdr: nftnlrdr.o nftnlrdr_misc.o testnftnlrdr.o upnpglobalvars.o $(LIBS)
|
testnftnlrdr: nftnlrdr.o nftnlrdr_misc.o testnftnlrdr.o $(LIBS)
|
||||||
|
|
||||||
testnftpinhole: nftpinhole.o nftnlrdr_misc.o testnftpinhole.o upnpglobalvars.o $(LIBS)
|
testnftpinhole: nftpinhole.o nftnlrdr_misc.o testnftpinhole.o $(LIBS)
|
||||||
|
|
||||||
test_nfct_get: test_nfct_get.o test_nfct_get.o -lmnl -lnetfilter_conntrack
|
test_nfct_get: test_nfct_get.o test_nfct_get.o -lmnl -lnetfilter_conntrack
|
||||||
|
|
||||||
|
@ -29,5 +29,3 @@ nftnlrdr_misc.o: nftnlrdr_misc.c
|
||||||
|
|
||||||
nftpinhole.o: nftpinhole.c nftpinhole.h
|
nftpinhole.o: nftpinhole.c nftpinhole.h
|
||||||
|
|
||||||
upnpglobalvars.o: ../upnpglobalvars.c ../upnpglobalvars.h
|
|
||||||
$(CC) -c -o $@ $<
|
|
||||||
|
|
|
@ -20,14 +20,18 @@
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
#include <linux/netfilter.h>
|
#include <linux/netfilter.h>
|
||||||
|
#include <linux/netfilter_ipv4.h>
|
||||||
#include <linux/netfilter/nfnetlink.h>
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
#include <linux/netfilter/nf_tables.h>
|
#include <linux/netfilter/nf_tables.h>
|
||||||
|
|
||||||
#include <libmnl/libmnl.h>
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnftnl/table.h>
|
||||||
|
#include <libnftnl/chain.h>
|
||||||
#include <libnftnl/rule.h>
|
#include <libnftnl/rule.h>
|
||||||
#include <libnftnl/expr.h>
|
#include <libnftnl/expr.h>
|
||||||
|
|
||||||
|
@ -35,8 +39,8 @@
|
||||||
|
|
||||||
#include "../macros.h"
|
#include "../macros.h"
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
#include "../commonrdr.h"
|
||||||
#include "nftnlrdr.h"
|
#include "nftnlrdr.h"
|
||||||
#include "../upnpglobalvars.h"
|
|
||||||
|
|
||||||
#include "nftnlrdr_misc.h"
|
#include "nftnlrdr_misc.h"
|
||||||
|
|
||||||
|
@ -56,15 +60,123 @@ struct timestamp_entry {
|
||||||
|
|
||||||
static struct timestamp_entry * timestamp_list = NULL;
|
static struct timestamp_entry * timestamp_list = NULL;
|
||||||
|
|
||||||
/* dummy init and shutdown functions */
|
#define NAT_CHAIN_TYPE "nat"
|
||||||
int init_redirect(void)
|
#define FILTER_CHAIN_TYPE "filter"
|
||||||
{
|
|
||||||
return 0;
|
/* init and shutdown functions */
|
||||||
|
int
|
||||||
|
init_redirect(void) {
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* 'inet' family */
|
||||||
|
result = table_op(NFT_MSG_NEWTABLE, NFPROTO_INET, nft_table);
|
||||||
|
if (result == 0) {
|
||||||
|
result = chain_op(NFT_MSG_NEWCHAIN, NFPROTO_INET, nft_table,
|
||||||
|
nft_forward_chain, FILTER_CHAIN_TYPE, NF_INET_FORWARD, NF_IP_PRI_FILTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'ip' family */
|
||||||
|
if (result == 0) {
|
||||||
|
result = table_op(NFT_MSG_NEWTABLE, NFPROTO_IPV4, nft_table4);
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
result = chain_op(NFT_MSG_NEWCHAIN, NFPROTO_IPV4, nft_table4,
|
||||||
|
nft_prerouting_chain, NAT_CHAIN_TYPE, NF_INET_PRE_ROUTING, NF_IP_PRI_NAT_DST);
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
result = chain_op(NFT_MSG_NEWCHAIN, NFPROTO_IPV4, nft_table4,
|
||||||
|
nft_postrouting_chain, NAT_CHAIN_TYPE, NF_INET_POST_ROUTING, NF_IP_PRI_NAT_SRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'ip6' family */
|
||||||
|
if (result == 0) {
|
||||||
|
result = table_op(NFT_MSG_NEWTABLE, NFPROTO_IPV6, nft_table6);
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
result = chain_op(NFT_MSG_NEWCHAIN, NFPROTO_IPV6, nft_table6,
|
||||||
|
nft_prerouting_chain, NAT_CHAIN_TYPE, NF_INET_PRE_ROUTING, NF_IP_PRI_NAT_DST);
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
result = chain_op(NFT_MSG_NEWCHAIN, NFPROTO_IPV6, nft_table6,
|
||||||
|
nft_postrouting_chain, NAT_CHAIN_TYPE, NF_INET_POST_ROUTING, NF_IP_PRI_NAT_SRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shutdown_redirect(void)
|
void
|
||||||
{
|
shutdown_redirect(void) {
|
||||||
return;
|
int result;
|
||||||
|
|
||||||
|
/* 'inet' family */
|
||||||
|
result = chain_op(NFT_MSG_DELCHAIN, NFPROTO_INET, nft_table,
|
||||||
|
nft_forward_chain, FILTER_CHAIN_TYPE, NF_INET_FORWARD, NF_IP_PRI_FILTER);
|
||||||
|
if (result == 0) {
|
||||||
|
result = table_op(NFT_MSG_DELTABLE, NFPROTO_INET, nft_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'ip' family */
|
||||||
|
result = chain_op(NFT_MSG_DELCHAIN, NFPROTO_IPV4, nft_table4,
|
||||||
|
nft_prerouting_chain, NAT_CHAIN_TYPE, NF_INET_PRE_ROUTING, NF_IP_PRI_NAT_DST);
|
||||||
|
if (result == 0) {
|
||||||
|
result = chain_op(NFT_MSG_DELCHAIN, NFPROTO_IPV4, nft_table4,
|
||||||
|
nft_postrouting_chain, NAT_CHAIN_TYPE, NF_INET_POST_ROUTING, NF_IP_PRI_NAT_SRC);
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
result = table_op(NFT_MSG_DELTABLE, NFPROTO_IPV4, nft_table4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'ip6' family */
|
||||||
|
if (result == 0) {
|
||||||
|
result = chain_op(NFT_MSG_DELCHAIN, NFPROTO_IPV6, nft_table6,
|
||||||
|
nft_prerouting_chain, NAT_CHAIN_TYPE, NF_INET_PRE_ROUTING, NF_IP_PRI_NAT_DST);
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
result = chain_op(NFT_MSG_DELCHAIN, NFPROTO_IPV6, nft_table6,
|
||||||
|
nft_postrouting_chain, NAT_CHAIN_TYPE, NF_INET_POST_ROUTING, NF_IP_PRI_NAT_SRC);
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
result = table_op(NFT_MSG_DELTABLE, NFPROTO_IPV6, nft_table6);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_batch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used by the core to override default chain names if specified in config file
|
||||||
|
* @param param which string to set
|
||||||
|
* @param string the new name to use. Do not dispose after setting (i.e. use strdup if not static).
|
||||||
|
* @return 0 if successful
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
set_rdr_name(rdr_name_type param, const char *string) {
|
||||||
|
if (string == NULL || strlen(string) > 30) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
switch (param) {
|
||||||
|
case TABLE_NAME:
|
||||||
|
nft_table = string;
|
||||||
|
break;
|
||||||
|
case TABLE4_NAME:
|
||||||
|
nft_table4 = string;
|
||||||
|
break;
|
||||||
|
case TABLE6_NAME:
|
||||||
|
nft_table6 = string;
|
||||||
|
break;
|
||||||
|
case NAT_CHAIN_NAME:
|
||||||
|
nft_prerouting_chain = string;
|
||||||
|
break;
|
||||||
|
case NAT_POSTROUTING_CHAIN_NAME:
|
||||||
|
nft_postrouting_chain = string;
|
||||||
|
break;
|
||||||
|
case FORWARD_CHAIN_NAME:
|
||||||
|
nft_forward_chain = string;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
syslog(LOG_ERR, "tried to set invalid string parameter: %d", param);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
|
@ -136,7 +248,7 @@ add_redirect_rule2(const char * ifname,
|
||||||
0, eport,
|
0, eport,
|
||||||
inet_addr(iaddr), iport, desc, NULL);
|
inet_addr(iaddr), iport, desc, NULL);
|
||||||
|
|
||||||
return nft_send_request(r, NFT_MSG_NEWRULE, RULE_CHAIN_REDIRECT);
|
return nft_send_rule(r, NFT_MSG_NEWRULE, RULE_CHAIN_REDIRECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -162,7 +274,7 @@ add_peer_redirect_rule2(const char * ifname,
|
||||||
inet_addr(eaddr), eport,
|
inet_addr(eaddr), eport,
|
||||||
inet_addr(iaddr), iport, desc, NULL);
|
inet_addr(iaddr), iport, desc, NULL);
|
||||||
|
|
||||||
return nft_send_request(r, NFT_MSG_NEWRULE, RULE_CHAIN_PEER);
|
return nft_send_rule(r, NFT_MSG_NEWRULE, RULE_CHAIN_PEER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -191,7 +303,7 @@ add_filter_rule2(const char * ifname,
|
||||||
eport, iport, 0,
|
eport, iport, 0,
|
||||||
desc, 0);
|
desc, 0);
|
||||||
|
|
||||||
return nft_send_request(r, NFT_MSG_NEWRULE, RULE_CHAIN_FILTER);
|
return nft_send_rule(r, NFT_MSG_NEWRULE, RULE_CHAIN_FILTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -219,11 +331,11 @@ delete_filter_rule(const char * ifname, unsigned short port, int proto)
|
||||||
struct nftnl_rule *r;
|
struct nftnl_rule *r;
|
||||||
UNUSED(ifname);
|
UNUSED(ifname);
|
||||||
|
|
||||||
reflesh_nft_cache_filter();
|
refresh_nft_cache_filter();
|
||||||
LIST_FOREACH(p, &head_filter, entry) {
|
LIST_FOREACH(p, &head_filter, entry) {
|
||||||
if (p->eport == port && p->proto == proto && p->type == RULE_FILTER) {
|
if (p->eport == port && p->proto == proto && p->type == RULE_FILTER) {
|
||||||
r = rule_del_handle(p);
|
r = rule_del_handle(p);
|
||||||
nft_send_request(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
|
nft_send_rule(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,7 +355,7 @@ delete_redirect_and_filter_rules(unsigned short eport, int proto)
|
||||||
uint16_t iport = 0;
|
uint16_t iport = 0;
|
||||||
|
|
||||||
d_printf(("delete_redirect_and_filter_rules(%d %d)\n", eport, proto));
|
d_printf(("delete_redirect_and_filter_rules(%d %d)\n", eport, proto));
|
||||||
reflesh_nft_cache_redirect();
|
refresh_nft_cache_redirect();
|
||||||
|
|
||||||
// Delete Redirect Rule
|
// Delete Redirect Rule
|
||||||
LIST_FOREACH(p, &head_redirect, entry) {
|
LIST_FOREACH(p, &head_redirect, entry) {
|
||||||
|
@ -254,20 +366,20 @@ delete_redirect_and_filter_rules(unsigned short eport, int proto)
|
||||||
|
|
||||||
r = rule_del_handle(p);
|
r = rule_del_handle(p);
|
||||||
/* Todo: send bulk request */
|
/* Todo: send bulk request */
|
||||||
nft_send_request(r, NFT_MSG_DELRULE, RULE_CHAIN_REDIRECT);
|
nft_send_rule(r, NFT_MSG_DELRULE, RULE_CHAIN_REDIRECT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iaddr != 0 && iport != 0) {
|
if (iaddr != 0 && iport != 0) {
|
||||||
reflesh_nft_cache_filter();
|
refresh_nft_cache_filter();
|
||||||
// Delete Forward Rule
|
// Delete Forward Rule
|
||||||
LIST_FOREACH(p, &head_filter, entry) {
|
LIST_FOREACH(p, &head_filter, entry) {
|
||||||
if (p->eport == iport &&
|
if (p->eport == iport &&
|
||||||
p->iaddr == iaddr && p->type == RULE_FILTER) {
|
p->iaddr == iaddr && p->type == RULE_FILTER) {
|
||||||
r = rule_del_handle(p);
|
r = rule_del_handle(p);
|
||||||
/* Todo: send bulk request */
|
/* Todo: send bulk request */
|
||||||
nft_send_request(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
|
nft_send_rule(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,7 +388,7 @@ delete_redirect_and_filter_rules(unsigned short eport, int proto)
|
||||||
iaddr = 0;
|
iaddr = 0;
|
||||||
iport = 0;
|
iport = 0;
|
||||||
|
|
||||||
reflesh_nft_cache_peer();
|
refresh_nft_cache_peer();
|
||||||
// Delete Peer Rule
|
// Delete Peer Rule
|
||||||
LIST_FOREACH(p, &head_peer, entry) {
|
LIST_FOREACH(p, &head_peer, entry) {
|
||||||
if (p->eport == eport && p->proto == proto &&
|
if (p->eport == eport && p->proto == proto &&
|
||||||
|
@ -286,20 +398,20 @@ delete_redirect_and_filter_rules(unsigned short eport, int proto)
|
||||||
|
|
||||||
r = rule_del_handle(p);
|
r = rule_del_handle(p);
|
||||||
/* Todo: send bulk request */
|
/* Todo: send bulk request */
|
||||||
nft_send_request(r, NFT_MSG_DELRULE, RULE_CHAIN_PEER);
|
nft_send_rule(r, NFT_MSG_DELRULE, RULE_CHAIN_PEER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iaddr != 0 && iport != 0) {
|
if (iaddr != 0 && iport != 0) {
|
||||||
reflesh_nft_cache_filter();
|
refresh_nft_cache_filter();
|
||||||
// Delete Forward Rule
|
// Delete Forward Rule
|
||||||
LIST_FOREACH(p, &head_filter, entry) {
|
LIST_FOREACH(p, &head_filter, entry) {
|
||||||
if (p->eport == iport &&
|
if (p->eport == iport &&
|
||||||
p->iaddr == iaddr && p->type == RULE_FILTER) {
|
p->iaddr == iaddr && p->type == RULE_FILTER) {
|
||||||
r = rule_del_handle(p);
|
r = rule_del_handle(p);
|
||||||
/* Todo: send bulk request */
|
/* Todo: send bulk request */
|
||||||
nft_send_request(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
|
nft_send_rule(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +439,7 @@ get_peer_rule_by_index(int index,
|
||||||
UNUSED(timestamp);
|
UNUSED(timestamp);
|
||||||
|
|
||||||
d_printf(("get_peer_rule_by_index()\n"));
|
d_printf(("get_peer_rule_by_index()\n"));
|
||||||
reflesh_nft_cache_peer();
|
refresh_nft_cache_peer();
|
||||||
|
|
||||||
LIST_FOREACH(r, &head_peer, entry) {
|
LIST_FOREACH(r, &head_peer, entry) {
|
||||||
if (r->index == index) {
|
if (r->index == index) {
|
||||||
|
@ -396,7 +508,7 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
|
||||||
unsigned int * timestamp,
|
unsigned int * timestamp,
|
||||||
u_int64_t * packets, u_int64_t * bytes)
|
u_int64_t * packets, u_int64_t * bytes)
|
||||||
{
|
{
|
||||||
return get_nat_redirect_rule(NFT_TABLE_NAT,
|
return get_nat_redirect_rule(nft_prerouting_chain,
|
||||||
ifname, eport, proto,
|
ifname, eport, proto,
|
||||||
iaddr, iaddrlen, iport,
|
iaddr, iaddrlen, iport,
|
||||||
desc, desclen,
|
desc, desclen,
|
||||||
|
@ -423,7 +535,7 @@ get_redirect_rule_by_index(int index,
|
||||||
UNUSED(timestamp);
|
UNUSED(timestamp);
|
||||||
|
|
||||||
d_printf(("get_redirect_rule_by_index()\n"));
|
d_printf(("get_redirect_rule_by_index()\n"));
|
||||||
reflesh_nft_cache_redirect();
|
refresh_nft_cache_redirect();
|
||||||
|
|
||||||
LIST_FOREACH(r, &head_redirect, entry) {
|
LIST_FOREACH(r, &head_redirect, entry) {
|
||||||
if (r->index == index) {
|
if (r->index == index) {
|
||||||
|
@ -504,7 +616,7 @@ get_nat_redirect_rule(const char * nat_chain_name, const char * ifname,
|
||||||
UNUSED(rhost);
|
UNUSED(rhost);
|
||||||
UNUSED(rhostlen);
|
UNUSED(rhostlen);
|
||||||
|
|
||||||
reflesh_nft_cache_redirect();
|
refresh_nft_cache_redirect();
|
||||||
|
|
||||||
LIST_FOREACH(p, &head_redirect, entry) {
|
LIST_FOREACH(p, &head_redirect, entry) {
|
||||||
if (p->proto == proto &&
|
if (p->proto == proto &&
|
||||||
|
@ -556,7 +668,7 @@ get_portmappings_in_range(unsigned short startport, unsigned short endport,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
reflesh_nft_cache_redirect();
|
refresh_nft_cache_redirect();
|
||||||
|
|
||||||
LIST_FOREACH(p, &head_redirect, entry) {
|
LIST_FOREACH(p, &head_redirect, entry) {
|
||||||
if (p->proto == proto &&
|
if (p->proto == proto &&
|
||||||
|
@ -636,17 +748,17 @@ list_redirect_rule(const char * ifname)
|
||||||
rule_t *p;
|
rule_t *p;
|
||||||
UNUSED(ifname);
|
UNUSED(ifname);
|
||||||
|
|
||||||
reflesh_nft_cache_filter();
|
refresh_nft_cache_filter();
|
||||||
LIST_FOREACH(p, &head_filter, entry) {
|
LIST_FOREACH(p, &head_filter, entry) {
|
||||||
print_rule(p);
|
print_rule(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
reflesh_nft_cache_redirect();
|
refresh_nft_cache_redirect();
|
||||||
LIST_FOREACH(p, &head_redirect, entry) {
|
LIST_FOREACH(p, &head_redirect, entry) {
|
||||||
print_rule(p);
|
print_rule(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
reflesh_nft_cache_peer();
|
refresh_nft_cache_peer();
|
||||||
LIST_FOREACH(p, &head_peer, entry) {
|
LIST_FOREACH(p, &head_peer, entry) {
|
||||||
print_rule(p);
|
print_rule(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define NFTNLRDR_H_INCLUDED
|
#define NFTNLRDR_H_INCLUDED
|
||||||
|
|
||||||
#include "../commonrdr.h"
|
#include "../commonrdr.h"
|
||||||
|
|
||||||
int init_redirect(void);
|
int init_redirect(void);
|
||||||
void shutdown_redirect(void);
|
void shutdown_redirect(void);
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,16 @@
|
||||||
#include <linux/ipv6.h>
|
#include <linux/ipv6.h>
|
||||||
|
|
||||||
#include <libmnl/libmnl.h>
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnftnl/table.h>
|
||||||
|
#include <libnftnl/chain.h>
|
||||||
#include <libnftnl/rule.h>
|
#include <libnftnl/rule.h>
|
||||||
#include <libnftnl/expr.h>
|
#include <libnftnl/expr.h>
|
||||||
|
|
||||||
|
#include "../commonrdr.h"
|
||||||
#include "nftnlrdr_misc.h"
|
#include "nftnlrdr_misc.h"
|
||||||
#include "../macros.h"
|
#include "../macros.h"
|
||||||
#include "../upnpglobalvars.h"
|
|
||||||
|
#define DEBUG 1
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define d_printf(x) do { printf x; } while (0)
|
#define d_printf(x) do { printf x; } while (0)
|
||||||
|
@ -45,10 +49,30 @@
|
||||||
#define d_printf(x)
|
#define d_printf(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(DEBUG) && (__STDC_VERSION__ >= 199901L) && (__GNUC__ >= 3)
|
||||||
|
/* disambiguate log messages by adding position in source. GNU C99 or later. Pesky trailing comma... */
|
||||||
|
#define log_error( msg, ...) syslog(LOG_ERR, "%s[%d]: " msg, __func__, __LINE__, ##__VA_ARGS__ )
|
||||||
|
#define log_debug( msg, ...) syslog(LOG_DEBUG, "%s[%d]: " msg, __func__, __LINE__, ##__VA_ARGS__ )
|
||||||
|
#else
|
||||||
|
/* original style */
|
||||||
|
#define log_error(args...) syslog(LOG_ERR, args)
|
||||||
|
#define log_debug(args...) syslog(LOG_DEBUG, args)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define RULE_CACHE_INVALID 0
|
#define RULE_CACHE_INVALID 0
|
||||||
#define RULE_CACHE_VALID 1
|
#define RULE_CACHE_VALID 1
|
||||||
|
|
||||||
|
const char * nft_table = "miniupnpd";
|
||||||
|
const char * nft_table4 = "miniupnpd4";
|
||||||
|
const char * nft_table6 = "miniupnpd6";
|
||||||
|
const char * nft_prerouting_chain = "prerouting";
|
||||||
|
const char * nft_postrouting_chain = "postrouting";
|
||||||
|
const char * nft_forward_chain = "forward";
|
||||||
|
|
||||||
static struct mnl_socket *nl = NULL;
|
static struct mnl_socket *nl = NULL;
|
||||||
|
static uint32_t nl_seq = 0;
|
||||||
|
|
||||||
// FILTER
|
// FILTER
|
||||||
struct rule_list head_filter = LIST_HEAD_INITIALIZER(head_filter);
|
struct rule_list head_filter = LIST_HEAD_INITIALIZER(head_filter);
|
||||||
// DNAT
|
// DNAT
|
||||||
|
@ -254,7 +278,7 @@ set_reg (rule_t *r, uint32_t dreg, enum rule_reg_type type, uint32_t val)
|
||||||
r->filter_action = val;
|
r->filter_action = val;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
syslog(LOG_ERR, "%s: unknown reg:%d", "set_reg", dreg);
|
log_error("unknown reg:%d", dreg);
|
||||||
}
|
}
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
@ -275,7 +299,6 @@ parse_rule_immediate(struct nftnl_expr *e, rule_t *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_reg(r, dreg, RULE_REG_IMM_VAL, reg_val);
|
set_reg(r, dreg, RULE_REG_IMM_VAL, reg_val);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -284,8 +307,6 @@ parse_rule_counter(struct nftnl_expr *e, rule_t *r)
|
||||||
r->type = RULE_COUNTER;
|
r->type = RULE_COUNTER;
|
||||||
r->bytes = nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_BYTES);
|
r->bytes = nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_BYTES);
|
||||||
r->packets = nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_PACKETS);
|
r->packets = nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_PACKETS);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -295,21 +316,20 @@ parse_rule_meta(struct nftnl_expr *e, rule_t *r)
|
||||||
uint32_t dreg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
|
uint32_t dreg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
|
||||||
enum rule_reg_type reg_type;
|
enum rule_reg_type reg_type;
|
||||||
|
|
||||||
|
/* ToDo: body of both cases are identical - bug? */
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case NFT_META_IIF:
|
case NFT_META_IIF:
|
||||||
reg_type = RULE_REG_IIF;
|
reg_type = RULE_REG_IIF;
|
||||||
set_reg(r, dreg, reg_type, 0);
|
set_reg(r, dreg, reg_type, 0);
|
||||||
return ;
|
break;
|
||||||
|
|
||||||
case NFT_META_OIF:
|
case NFT_META_OIF:
|
||||||
reg_type = RULE_REG_IIF;
|
reg_type = RULE_REG_IIF;
|
||||||
set_reg(r, dreg, reg_type, 0);
|
set_reg(r, dreg, reg_type, 0);
|
||||||
return ;
|
break;
|
||||||
|
default:
|
||||||
|
log_debug("parse_rule_meta :Not support key %d\n", key);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
syslog(LOG_DEBUG, "parse_rule_meta :Not support key %d\n", key);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -328,7 +348,7 @@ parse_rule_nat(struct nftnl_expr *e, rule_t *r)
|
||||||
|
|
||||||
if (addr_min_reg != addr_max_reg ||
|
if (addr_min_reg != addr_max_reg ||
|
||||||
proto_min_reg != proto_max_reg) {
|
proto_min_reg != proto_max_reg) {
|
||||||
syslog(LOG_ERR, "Unsupport proto/addr range for NAT");
|
log_error( "Unsupport proto/addr range for NAT");
|
||||||
}
|
}
|
||||||
|
|
||||||
proto_min_val = htons((uint16_t)*get_reg_val_ptr(r, proto_min_reg));
|
proto_min_val = htons((uint16_t)*get_reg_val_ptr(r, proto_min_reg));
|
||||||
|
@ -344,7 +364,6 @@ parse_rule_nat(struct nftnl_expr *e, rule_t *r)
|
||||||
|
|
||||||
set_reg(r, NFT_REG_1, RULE_REG_NONE, 0);
|
set_reg(r, NFT_REG_1, RULE_REG_NONE, 0);
|
||||||
set_reg(r, NFT_REG_2, RULE_REG_NONE, 0);
|
set_reg(r, NFT_REG_2, RULE_REG_NONE, 0);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -364,53 +383,45 @@ parse_rule_payload(struct nftnl_expr *e, rule_t *r)
|
||||||
if (offset == offsetof(struct iphdr, daddr) &&
|
if (offset == offsetof(struct iphdr, daddr) &&
|
||||||
len == sizeof(in_addr_t)) {
|
len == sizeof(in_addr_t)) {
|
||||||
*regptr = RULE_REG_IP_DEST_ADDR;
|
*regptr = RULE_REG_IP_DEST_ADDR;
|
||||||
return;
|
|
||||||
} else if (offset == offsetof(struct iphdr, saddr) &&
|
} else if (offset == offsetof(struct iphdr, saddr) &&
|
||||||
len == sizeof(in_addr_t)) {
|
len == sizeof(in_addr_t)) {
|
||||||
*regptr = RULE_REG_IP_SRC_ADDR;
|
*regptr = RULE_REG_IP_SRC_ADDR;
|
||||||
return;
|
|
||||||
} else if (offset == offsetof(struct iphdr, saddr) &&
|
} else if (offset == offsetof(struct iphdr, saddr) &&
|
||||||
len == sizeof(in_addr_t) * 2) {
|
len == sizeof(in_addr_t) * 2) {
|
||||||
*regptr = RULE_REG_IP_SD_ADDR;
|
*regptr = RULE_REG_IP_SD_ADDR;
|
||||||
return;
|
|
||||||
} else if (offset == offsetof(struct iphdr, protocol) &&
|
} else if (offset == offsetof(struct iphdr, protocol) &&
|
||||||
len == sizeof(uint8_t)) {
|
len == sizeof(uint8_t)) {
|
||||||
*regptr = RULE_REG_IP_PROTO;
|
*regptr = RULE_REG_IP_PROTO;
|
||||||
return;
|
|
||||||
} else if (offset == offsetof(struct ipv6hdr, nexthdr) &&
|
} else if (offset == offsetof(struct ipv6hdr, nexthdr) &&
|
||||||
len == sizeof(uint8_t)) {
|
len == sizeof(uint8_t)) {
|
||||||
*regptr = RULE_REG_IP6_PROTO;
|
*regptr = RULE_REG_IP6_PROTO;
|
||||||
return;
|
|
||||||
} else if (offset == offsetof(struct ipv6hdr, daddr) &&
|
} else if (offset == offsetof(struct ipv6hdr, daddr) &&
|
||||||
len == sizeof(struct in6_addr)) {
|
len == sizeof(struct in6_addr)) {
|
||||||
*regptr = RULE_REG_IP6_DEST_ADDR;
|
*regptr = RULE_REG_IP6_DEST_ADDR;
|
||||||
return;
|
|
||||||
} else if (offset == offsetof(struct ipv6hdr, saddr) &&
|
} else if (offset == offsetof(struct ipv6hdr, saddr) &&
|
||||||
len == sizeof(struct in6_addr)) {
|
len == sizeof(struct in6_addr)) {
|
||||||
*regptr = RULE_REG_IP6_SRC_ADDR;
|
*regptr = RULE_REG_IP6_SRC_ADDR;
|
||||||
return;
|
|
||||||
} else if (offset == offsetof(struct ipv6hdr, saddr) &&
|
} else if (offset == offsetof(struct ipv6hdr, saddr) &&
|
||||||
len == sizeof(struct in6_addr) * 2) {
|
len == sizeof(struct in6_addr) * 2) {
|
||||||
*regptr = RULE_REG_IP6_SD_ADDR;
|
*regptr = RULE_REG_IP6_SD_ADDR;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NFT_PAYLOAD_TRANSPORT_HEADER:
|
case NFT_PAYLOAD_TRANSPORT_HEADER:
|
||||||
if (offset == offsetof(struct tcphdr, dest) &&
|
if (offset == offsetof(struct tcphdr, dest) &&
|
||||||
len == sizeof(uint16_t)) {
|
len == sizeof(uint16_t)) {
|
||||||
*regptr = RULE_REG_TCP_DPORT;
|
*regptr = RULE_REG_TCP_DPORT;
|
||||||
return;
|
|
||||||
} else if (offset == offsetof(struct tcphdr, source) &&
|
} else if (offset == offsetof(struct tcphdr, source) &&
|
||||||
len == sizeof(uint16_t) * 2) {
|
len == sizeof(uint16_t) * 2) {
|
||||||
*regptr = RULE_REG_TCP_SD_PORT;
|
*regptr = RULE_REG_TCP_SD_PORT;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
syslog(LOG_DEBUG,
|
||||||
|
"Unsupported payload: (dreg:%d, base:%d, offset:%d, len:%d)",
|
||||||
|
dreg, base, offset, len);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
syslog(LOG_DEBUG,
|
|
||||||
"Unsupport payload: (dreg:%d, base:%d, offset:%d, len:%d)",
|
|
||||||
dreg, base, offset, len);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -436,7 +447,7 @@ parse_rule_cmp(struct nftnl_expr *e, rule_t *r) {
|
||||||
sreg = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_SREG);
|
sreg = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_SREG);
|
||||||
|
|
||||||
if (sreg != NFT_REG_1) {
|
if (sreg != NFT_REG_1) {
|
||||||
syslog(LOG_ERR, "parse_rule_cmp: Unsupport reg:%d", sreg);
|
log_error( "parse_rule_cmp: Unsupport reg:%d", sreg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,7 +520,7 @@ parse_rule_cmp(struct nftnl_expr *e, rule_t *r) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
syslog(LOG_DEBUG, "Unknown cmp (r1type:%d, data_len:%d, op:%d)",
|
log_debug("Unknown cmp (r1type:%d, data_len:%d, op:%d)",
|
||||||
r->reg1_type, data_len, op);
|
r->reg1_type, data_len, op);
|
||||||
/* return early - don't modify r->reg1_type */
|
/* return early - don't modify r->reg1_type */
|
||||||
return;
|
return;
|
||||||
|
@ -538,7 +549,7 @@ rule_expr_cb(struct nftnl_expr *e, void *data)
|
||||||
} else if (strncmp("immediate", attr_name, sizeof("immediate")) == 0) {
|
} else if (strncmp("immediate", attr_name, sizeof("immediate")) == 0) {
|
||||||
parse_rule_immediate(e, r);
|
parse_rule_immediate(e, r);
|
||||||
} else {
|
} else {
|
||||||
syslog(LOG_DEBUG, "unknown attr: %s\n", attr_name);
|
log_debug("unknown attr: %s\n", attr_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MNL_CB_OK;
|
return MNL_CB_OK;
|
||||||
|
@ -548,6 +559,7 @@ rule_expr_cb(struct nftnl_expr *e, void *data)
|
||||||
static int
|
static int
|
||||||
table_cb(const struct nlmsghdr *nlh, void *data)
|
table_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
{
|
{
|
||||||
|
int result = MNL_CB_OK;
|
||||||
struct nftnl_rule *t;
|
struct nftnl_rule *t;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
struct nftnl_expr *expr;
|
struct nftnl_expr *expr;
|
||||||
|
@ -562,130 +574,118 @@ table_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
|
||||||
r = malloc(sizeof(rule_t));
|
r = malloc(sizeof(rule_t));
|
||||||
|
|
||||||
memset(r, 0, sizeof(rule_t));
|
if (r == NULL) {
|
||||||
t = nftnl_rule_alloc();
|
log_error("out of memory: %m");
|
||||||
if (t == NULL) {
|
} else {
|
||||||
syslog(LOG_ERR, "nftnl_rule_alloc() FAILED");
|
memset(r, 0, sizeof(rule_t));
|
||||||
goto err;
|
t = nftnl_rule_alloc();
|
||||||
|
if (t == NULL) {
|
||||||
|
log_error("nftnl_rule_alloc() FAILED");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (nftnl_rule_nlmsg_parse(nlh, t) < 0) {
|
||||||
|
log_error("nftnl_rule_nlmsg_parse FAILED");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
chain = (char *) nftnl_rule_get_data(t, NFTNL_RULE_CHAIN, &len);
|
||||||
|
if (strcmp(chain, nft_prerouting_chain) == 0 ||
|
||||||
|
strcmp(chain, nft_postrouting_chain) == 0 ||
|
||||||
|
strcmp(chain, nft_forward_chain) == 0) {
|
||||||
|
r->table = strdup(
|
||||||
|
(char *) nftnl_rule_get_data(t, NFTNL_RULE_TABLE, &len));
|
||||||
|
r->chain = strdup(chain);
|
||||||
|
r->family = *(uint32_t *) nftnl_rule_get_data(t, NFTNL_RULE_FAMILY,
|
||||||
|
&len);
|
||||||
|
descr = (char *) nftnl_rule_get_data(t, NFTNL_RULE_USERDATA,
|
||||||
|
&r->desc_len);
|
||||||
|
if (r->desc_len > 0)
|
||||||
|
r->desc = strdup(descr);
|
||||||
|
|
||||||
|
r->handle = *(uint32_t *) nftnl_rule_get_data(t,
|
||||||
|
NFTNL_RULE_HANDLE,
|
||||||
|
&len);
|
||||||
|
r->type = RULE_NONE;
|
||||||
|
if (strcmp(chain, nft_prerouting_chain) == 0 ||
|
||||||
|
strcmp(chain, nft_postrouting_chain) == 0) {
|
||||||
|
r->type = RULE_NAT;
|
||||||
|
} else if (strcmp(chain, nft_forward_chain) == 0) {
|
||||||
|
r->type = RULE_FILTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
itr = nftnl_expr_iter_create(t);
|
||||||
|
|
||||||
|
while ((expr = nftnl_expr_iter_next(itr)) != NULL) {
|
||||||
|
rule_expr_cb(expr, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (r->type) {
|
||||||
|
case RULE_NAT:
|
||||||
|
switch (r->nat_type) {
|
||||||
|
case NFT_NAT_SNAT:
|
||||||
|
r->index = index_peer;
|
||||||
|
LIST_INSERT_HEAD(&head_peer, r, entry);
|
||||||
|
index_peer++;
|
||||||
|
break;
|
||||||
|
case NFT_NAT_DNAT:
|
||||||
|
r->index = index_redirect;
|
||||||
|
LIST_INSERT_HEAD(&head_redirect, r, entry);
|
||||||
|
index_redirect++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RULE_FILTER:
|
||||||
|
r->index = index_filter;
|
||||||
|
LIST_INSERT_HEAD(&head_filter, r, entry);
|
||||||
|
index_filter++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
free(r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nftnl_rule_free(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
if (nftnl_rule_nlmsg_parse(nlh, t) < 0) {
|
|
||||||
syslog(LOG_ERR, "nftnl_rule_nlmsg_parse FAILED");
|
|
||||||
goto err_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
chain = (char *)nftnl_rule_get_data(t, NFTNL_RULE_CHAIN, &len);
|
|
||||||
if (strcmp(chain, miniupnpd_nat_chain) != 0 &&
|
|
||||||
strcmp(chain, miniupnpd_nat_postrouting_chain) != 0 &&
|
|
||||||
strcmp(chain, miniupnpd_forward_chain) != 0) {
|
|
||||||
goto rule_skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->table = strdup(
|
|
||||||
(char *)nftnl_rule_get_data(t, NFTNL_RULE_TABLE, &len));
|
|
||||||
r->chain = strdup(chain);
|
|
||||||
r->family = *(uint32_t*)nftnl_rule_get_data(t, NFTNL_RULE_FAMILY,
|
|
||||||
&len);
|
|
||||||
descr = (char *)nftnl_rule_get_data(t, NFTNL_RULE_USERDATA,
|
|
||||||
&r->desc_len);
|
|
||||||
if (r->desc_len > 0)
|
|
||||||
r->desc = strdup(descr);
|
|
||||||
|
|
||||||
r->handle = *(uint32_t*)nftnl_rule_get_data(t,
|
|
||||||
NFTNL_RULE_HANDLE,
|
|
||||||
&len);
|
|
||||||
if (strcmp(r->table, NFT_TABLE_NAT) == 0) {
|
|
||||||
r->type = RULE_NAT;
|
|
||||||
} else if (strcmp(r->table, NFT_TABLE_FILTER) == 0) {
|
|
||||||
r->type = RULE_FILTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
itr = nftnl_expr_iter_create(t);
|
|
||||||
|
|
||||||
while ((expr = nftnl_expr_iter_next(itr)) != NULL) {
|
|
||||||
rule_expr_cb(expr, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r->type == RULE_NONE) {
|
|
||||||
free(r);
|
|
||||||
} else if (r->type == RULE_NAT && r->nat_type == NFT_NAT_SNAT) {
|
|
||||||
r->index = index_peer;
|
|
||||||
LIST_INSERT_HEAD(&head_peer, r, entry);
|
|
||||||
index_peer++;
|
|
||||||
} else if (r->type == RULE_NAT && r->nat_type == NFT_NAT_DNAT) {
|
|
||||||
r->index = index_redirect;
|
|
||||||
LIST_INSERT_HEAD(&head_redirect, r, entry);
|
|
||||||
index_redirect++;
|
|
||||||
} else if (r->type == RULE_FILTER) {
|
|
||||||
r->index = index_filter;
|
|
||||||
LIST_INSERT_HEAD(&head_filter, r, entry);
|
|
||||||
index_filter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
rule_skip:
|
|
||||||
err_free:
|
|
||||||
nftnl_rule_free(t);
|
|
||||||
err:
|
|
||||||
return MNL_CB_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
reflesh_nft_cache_filter()
|
refresh_nft_cache_filter(void) {
|
||||||
{
|
if (rule_list_filter_validate != RULE_CACHE_VALID) {
|
||||||
|
refresh_nft_cache(&head_filter, nft_table4, nft_forward_chain, NFPROTO_INET);
|
||||||
if (rule_list_filter_validate == RULE_CACHE_VALID) {
|
rule_list_filter_validate = RULE_CACHE_VALID;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reflesh_nft_cache(&head_filter, NFT_TABLE_FILTER, miniupnpd_forward_chain, NFPROTO_INET);
|
|
||||||
|
|
||||||
rule_list_filter_validate = RULE_CACHE_VALID;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
reflesh_nft_cache_peer()
|
refresh_nft_cache_peer(void) {
|
||||||
{
|
if (rule_list_peer_validate != RULE_CACHE_VALID) {
|
||||||
if (rule_list_peer_validate == RULE_CACHE_VALID) {
|
refresh_nft_cache(&head_peer, nft_table4, nft_postrouting_chain, NFPROTO_IPV4);
|
||||||
return;
|
rule_list_peer_validate = RULE_CACHE_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
reflesh_nft_cache(&head_peer, NFT_TABLE_NAT, miniupnpd_nat_postrouting_chain, NFPROTO_IPV4);
|
|
||||||
|
|
||||||
rule_list_peer_validate = RULE_CACHE_VALID;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
reflesh_nft_cache_redirect()
|
refresh_nft_cache_redirect(void)
|
||||||
{
|
{
|
||||||
if (rule_list_redirect_validate == RULE_CACHE_VALID) {
|
if (rule_list_redirect_validate != RULE_CACHE_VALID) {
|
||||||
return;
|
refresh_nft_cache(&head_redirect, nft_table4, nft_prerouting_chain, NFPROTO_IPV4);
|
||||||
|
rule_list_redirect_validate = RULE_CACHE_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
reflesh_nft_cache(&head_redirect, NFT_TABLE_NAT, miniupnpd_nat_chain, NFPROTO_IPV4);
|
|
||||||
|
|
||||||
rule_list_redirect_validate = RULE_CACHE_VALID;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
reflesh_nft_cache(struct rule_list *head, char *table, const char *chain, uint32_t family)
|
flush_nft_cache(struct rule_list *head)
|
||||||
{
|
{
|
||||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
|
||||||
struct nlmsghdr *nlh;
|
|
||||||
uint32_t portid, seq, type = NFTNL_OUTPUT_DEFAULT;
|
|
||||||
struct nftnl_rule *t;
|
|
||||||
rule_t *p1, *p2;
|
rule_t *p1, *p2;
|
||||||
int ret;
|
|
||||||
|
|
||||||
t = NULL;
|
|
||||||
p1 = LIST_FIRST(head);
|
p1 = LIST_FIRST(head);
|
||||||
if (p1 != NULL) {
|
if (p1 != NULL) {
|
||||||
while(p1 != NULL) {
|
while (p1 != NULL) {
|
||||||
p2 = (rule_t *)LIST_NEXT(p1, entry);
|
p2 = (rule_t *)LIST_NEXT(p1, entry);
|
||||||
if (p1->desc != NULL) {
|
if (p1->desc != NULL) {
|
||||||
free(p1->desc);
|
free(p1->desc);
|
||||||
|
@ -701,16 +701,28 @@ reflesh_nft_cache(struct rule_list *head, char *table, const char *chain, uint32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LIST_INIT(head);
|
LIST_INIT(head);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
refresh_nft_cache(struct rule_list *head, const char *table, const char *chain, uint32_t family)
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
uint32_t portid, seq, type = NFTNL_OUTPUT_DEFAULT;
|
||||||
|
struct nftnl_rule *t;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
flush_nft_cache(head);
|
||||||
|
|
||||||
if (nl == NULL) {
|
if (nl == NULL) {
|
||||||
nl = mnl_socket_open(NETLINK_NETFILTER);
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
if (nl == NULL) {
|
if (nl == NULL) {
|
||||||
syslog(LOG_ERR, "%s: mnl_socket_open() FAILED: %m", "reflesh_nft_cache()");
|
log_error("mnl_socket_open() FAILED: %m");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
syslog(LOG_ERR, "%s: mnl_socket_bind() FAILED: %m", "reflesh_nft_cache()");
|
log_error("mnl_socket_bind() FAILED: %m");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -718,7 +730,7 @@ reflesh_nft_cache(struct rule_list *head, char *table, const char *chain, uint32
|
||||||
|
|
||||||
t = nftnl_rule_alloc();
|
t = nftnl_rule_alloc();
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
syslog(LOG_ERR, "%s: nftnl_rule_alloc() FAILED", "reflesh_nft_cache()");
|
log_error("nftnl_rule_alloc() FAILED");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,7 +743,7 @@ reflesh_nft_cache(struct rule_list *head, char *table, const char *chain, uint32
|
||||||
nftnl_rule_free(t);
|
nftnl_rule_free(t);
|
||||||
|
|
||||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
syslog(LOG_ERR, "%s: mnl_socket_sendto() FAILED: %m", "reflesh_nft_cache()");
|
log_error("mnl_socket_sendto() FAILED: %m");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -744,7 +756,7 @@ reflesh_nft_cache(struct rule_list *head, char *table, const char *chain, uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
syslog(LOG_ERR, "%s: mnl_socket_recvfrom() FAILED: %m", "reflesh_nft_cache()");
|
log_error("mnl_socket_recvfrom() FAILED: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mnl_socket_close(nl); */
|
/* mnl_socket_close(nl); */
|
||||||
|
@ -760,7 +772,7 @@ expr_add_payload(struct nftnl_rule *r, uint32_t base, uint32_t dreg,
|
||||||
|
|
||||||
e = nftnl_expr_alloc("payload");
|
e = nftnl_expr_alloc("payload");
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
syslog(LOG_ERR, "%s: nftnl_expr_alloc(\"%s\") FAILED", "expr_add_payload()", "payload");
|
log_error("nftnl_expr_alloc(\"%s\") FAILED", "payload");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,7 +793,7 @@ expr_add_bitwise(struct nftnl_rule *r, uint32_t sreg, uint32_t dreg,
|
||||||
|
|
||||||
e = nftnl_expr_alloc("bitwise");
|
e = nftnl_expr_alloc("bitwise");
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
syslog(LOG_ERR, "%s: nftnl_expr_alloc(\"%s\") FAILED", "expr_add_bitwise()", "bitwise");
|
log_error("nftnl_expr_alloc(\"%s\") FAILED", "expr_add_bitwise()", "bitwise");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,7 +815,7 @@ expr_add_cmp(struct nftnl_rule *r, uint32_t sreg, uint32_t op,
|
||||||
|
|
||||||
e = nftnl_expr_alloc("cmp");
|
e = nftnl_expr_alloc("cmp");
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
syslog(LOG_ERR, "%s: nftnl_expr_alloc(\"%s\") FAILED", "expr_add_cmp()", "cmp");
|
log_error("nftnl_expr_alloc(\"%s\") FAILED", "cmp");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,7 +833,7 @@ expr_add_meta(struct nftnl_rule *r, uint32_t meta_key, uint32_t dreg)
|
||||||
|
|
||||||
e = nftnl_expr_alloc("meta");
|
e = nftnl_expr_alloc("meta");
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
syslog(LOG_ERR, "%s: nftnl_expr_alloc(\"%s\") FAILED", "expr_add_meta()", "meta");
|
log_error("nftnl_expr_alloc(\"%s\") FAILED", "meta");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,7 +849,7 @@ expr_set_reg_val_u32(struct nftnl_rule *r, enum nft_registers dreg, uint32_t val
|
||||||
struct nftnl_expr *e;
|
struct nftnl_expr *e;
|
||||||
e = nftnl_expr_alloc("immediate");
|
e = nftnl_expr_alloc("immediate");
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
syslog(LOG_ERR, "%s: nftnl_expr_alloc(\"%s\") FAILED", "expr_set_reg_val_u32()", "immediate");
|
log_error("nftnl_expr_alloc(\"%s\") FAILED", "immediate");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nftnl_expr_set_u32(e, NFTNL_EXPR_IMM_DREG, dreg);
|
nftnl_expr_set_u32(e, NFTNL_EXPR_IMM_DREG, dreg);
|
||||||
|
@ -851,7 +863,7 @@ expr_set_reg_val_u16(struct nftnl_rule *r, enum nft_registers dreg, uint32_t val
|
||||||
struct nftnl_expr *e;
|
struct nftnl_expr *e;
|
||||||
e = nftnl_expr_alloc("immediate");
|
e = nftnl_expr_alloc("immediate");
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
syslog(LOG_ERR, "%s: nftnl_expr_alloc(\"%s\") FAILED", "expr_set_reg_val_u16()", "immediate");
|
log_error("nftnl_expr_alloc(\"%s\") FAILED", "immediate");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nftnl_expr_set_u32(e, NFTNL_EXPR_IMM_DREG, dreg);
|
nftnl_expr_set_u32(e, NFTNL_EXPR_IMM_DREG, dreg);
|
||||||
|
@ -865,7 +877,7 @@ expr_set_reg_verdict(struct nftnl_rule *r, uint32_t val)
|
||||||
struct nftnl_expr *e;
|
struct nftnl_expr *e;
|
||||||
e = nftnl_expr_alloc("immediate");
|
e = nftnl_expr_alloc("immediate");
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
syslog(LOG_ERR, "%s: nftnl_expr_alloc(\"%s\") FAILED", "expr_set_reg_verdict()", "immediate");
|
log_error("nftnl_expr_alloc(\"%s\") FAILED", "immediate");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nftnl_expr_set_u32(e, NFTNL_EXPR_IMM_DREG, NFT_REG_VERDICT);
|
nftnl_expr_set_u32(e, NFTNL_EXPR_IMM_DREG, NFT_REG_VERDICT);
|
||||||
|
@ -882,7 +894,7 @@ expr_add_nat(struct nftnl_rule *r, uint32_t t, uint32_t family,
|
||||||
|
|
||||||
e = nftnl_expr_alloc("nat");
|
e = nftnl_expr_alloc("nat");
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
syslog(LOG_ERR, "%s: nftnl_expr_alloc(\"%s\") FAILED", "expr_add_nat()", "nat");
|
log_error("nftnl_expr_alloc(\"%s\") FAILED", "nat");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,12 +931,12 @@ rule_set_snat(uint8_t family, uint8_t proto,
|
||||||
|
|
||||||
r = nftnl_rule_alloc();
|
r = nftnl_rule_alloc();
|
||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
syslog(LOG_ERR, "nftnl_rule_alloc() FAILED");
|
log_error("nftnl_rule_alloc() FAILED");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
nftnl_rule_set(r, NFTNL_RULE_TABLE, NFT_TABLE_NAT);
|
nftnl_rule_set(r, NFTNL_RULE_TABLE, family == NFPROTO_IPV6 ? nft_table6 : nft_table4);
|
||||||
nftnl_rule_set(r, NFTNL_RULE_CHAIN, miniupnpd_nat_postrouting_chain);
|
nftnl_rule_set(r, NFTNL_RULE_CHAIN, nft_postrouting_chain);
|
||||||
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
|
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
|
||||||
|
|
||||||
if (descr != NULL) {
|
if (descr != NULL) {
|
||||||
|
@ -1005,12 +1017,12 @@ rule_set_dnat(uint8_t family, const char * ifname, uint8_t proto,
|
||||||
|
|
||||||
r = nftnl_rule_alloc();
|
r = nftnl_rule_alloc();
|
||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
syslog(LOG_ERR, "nftnl_rule_alloc() FAILED");
|
log_error("nftnl_rule_alloc() FAILED");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
nftnl_rule_set(r, NFTNL_RULE_TABLE, NFT_TABLE_NAT);
|
nftnl_rule_set(r, NFTNL_RULE_TABLE, family == NFPROTO_IPV6 ? nft_table6 : nft_table4);
|
||||||
nftnl_rule_set(r, NFTNL_RULE_CHAIN, miniupnpd_nat_chain);
|
nftnl_rule_set(r, NFTNL_RULE_CHAIN, nft_prerouting_chain);
|
||||||
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
|
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
|
||||||
|
|
||||||
if (descr != NULL) {
|
if (descr != NULL) {
|
||||||
|
@ -1079,7 +1091,7 @@ rule_set_filter(uint8_t family, const char * ifname, uint8_t proto,
|
||||||
|
|
||||||
r = nftnl_rule_alloc();
|
r = nftnl_rule_alloc();
|
||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
syslog(LOG_ERR, "nftnl_rule_alloc() FAILED");
|
log_error("nftnl_rule_alloc() FAILED");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,7 +1139,7 @@ rule_set_filter6(uint8_t family, const char * ifname, uint8_t proto,
|
||||||
|
|
||||||
r = nftnl_rule_alloc();
|
r = nftnl_rule_alloc();
|
||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
syslog(LOG_ERR, "nftnl_rule_alloc() FAILED");
|
log_error("nftnl_rule_alloc() FAILED");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1171,8 +1183,8 @@ rule_set_filter_common(struct nftnl_rule *r, uint8_t family, const char * ifname
|
||||||
uint32_t descr_len;
|
uint32_t descr_len;
|
||||||
UNUSED(eport);
|
UNUSED(eport);
|
||||||
|
|
||||||
nftnl_rule_set(r, NFTNL_RULE_TABLE, NFT_TABLE_FILTER);
|
nftnl_rule_set(r, NFTNL_RULE_TABLE, nft_table);
|
||||||
nftnl_rule_set(r, NFTNL_RULE_CHAIN, miniupnpd_forward_chain);
|
nftnl_rule_set(r, NFTNL_RULE_CHAIN, nft_forward_chain);
|
||||||
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
|
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
|
||||||
|
|
||||||
if (descr != NULL) {
|
if (descr != NULL) {
|
||||||
|
@ -1227,7 +1239,7 @@ rule_del_handle(rule_t *rule)
|
||||||
|
|
||||||
r = nftnl_rule_alloc();
|
r = nftnl_rule_alloc();
|
||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
syslog(LOG_ERR, "nftnl_rule_alloc() FAILED");
|
log_error("nftnl_rule_alloc() FAILED");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1257,75 +1269,204 @@ nft_mnl_batch_put(char *buf, uint16_t type, uint32_t seq)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nft_send_request(struct nftnl_rule * rule, uint16_t cmd, enum rule_chain_type chain_type)
|
nft_send_rule(struct nftnl_rule * rule, uint16_t cmd, enum rule_chain_type chain_type)
|
||||||
{
|
{
|
||||||
|
int result = -1;
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
struct mnl_nlmsg_batch *batch;
|
struct mnl_nlmsg_batch *batch;
|
||||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
uint32_t seq = time(NULL);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (chain_type == RULE_CHAIN_FILTER)
|
|
||||||
rule_list_filter_validate = RULE_CACHE_INVALID;
|
|
||||||
else if (chain_type == RULE_CHAIN_PEER)
|
|
||||||
rule_list_peer_validate = RULE_CACHE_INVALID;
|
|
||||||
else if (chain_type == RULE_CHAIN_REDIRECT)
|
|
||||||
rule_list_redirect_validate = RULE_CACHE_INVALID;
|
|
||||||
|
|
||||||
if (nl == NULL) {
|
batch = start_batch(buf, sizeof(buf));
|
||||||
nl = mnl_socket_open(NETLINK_NETFILTER);
|
if (batch != NULL)
|
||||||
if (nl == NULL) {
|
{
|
||||||
syslog(LOG_ERR, "%s: mnl_socket_open() FAILED: %m", "nft_send_request()");
|
switch (chain_type) {
|
||||||
return -1;
|
case RULE_CHAIN_FILTER:
|
||||||
}
|
rule_list_filter_validate = RULE_CACHE_INVALID;
|
||||||
|
break;
|
||||||
|
case RULE_CHAIN_PEER:
|
||||||
|
rule_list_peer_validate = RULE_CACHE_INVALID;
|
||||||
|
break;
|
||||||
|
case RULE_CHAIN_REDIRECT:
|
||||||
|
rule_list_redirect_validate = RULE_CACHE_INVALID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
|
||||||
|
cmd,
|
||||||
|
nftnl_rule_get_u32(rule, NFTNL_RULE_FAMILY),
|
||||||
|
NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK,
|
||||||
|
nl_seq++);
|
||||||
|
|
||||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
nftnl_rule_nlmsg_build_payload(nlh, rule);
|
||||||
syslog(LOG_ERR, "%s: mnl_socket_bind() FAILED: %m", "nft_send_request()");
|
nftnl_rule_free(rule);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
|
result = send_batch(batch);
|
||||||
|
}
|
||||||
|
|
||||||
nft_mnl_batch_put(mnl_nlmsg_batch_current(batch),
|
return result;
|
||||||
NFNL_MSG_BATCH_BEGIN, seq++);
|
}
|
||||||
mnl_nlmsg_batch_next(batch);
|
|
||||||
|
int
|
||||||
nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
|
table_op( enum nf_tables_msg_types op, uint16_t family, const char * name)
|
||||||
cmd,
|
{
|
||||||
nftnl_rule_get_u32(rule, NFTNL_RULE_FAMILY),
|
int result;
|
||||||
NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK,
|
struct nlmsghdr *nlh;
|
||||||
seq++);
|
struct mnl_nlmsg_batch *batch;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
nftnl_rule_nlmsg_build_payload(nlh, rule);
|
|
||||||
nftnl_rule_free(rule);
|
struct nftnl_table *table;
|
||||||
mnl_nlmsg_batch_next(batch);
|
|
||||||
|
log_error("(%d, %d, %s)", op, family, name);
|
||||||
nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_END,
|
|
||||||
seq++);
|
table = nftnl_table_alloc();
|
||||||
mnl_nlmsg_batch_next(batch);
|
if (table == NULL) {
|
||||||
|
log_error("out of memory: %m");
|
||||||
ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch),
|
result = -1;
|
||||||
mnl_nlmsg_batch_size(batch));
|
} else {
|
||||||
if (ret == -1) {
|
nftnl_table_set_u32(table, NFTNL_TABLE_FAMILY, family);
|
||||||
syslog(LOG_ERR, "%s: mnl_socket_sendto() FAILED: %m", "nft_send_request()");
|
nftnl_table_set_str(table, NFTNL_TABLE_NAME, name);
|
||||||
return -1;
|
|
||||||
}
|
batch = start_batch( buf, sizeof(buf));
|
||||||
|
if (batch == NULL) {
|
||||||
mnl_nlmsg_batch_stop(batch);
|
log_error("out of memory: %m");
|
||||||
|
result = -2;
|
||||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
} else {
|
||||||
if (ret == -1) {
|
nlh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
|
||||||
syslog(LOG_ERR, "%s: mnl_socket_recvfrom() FAILED: %m", "nft_send_request()");
|
op, family,
|
||||||
return -1;
|
(op == NFT_MSG_NEWTABLE ? NLM_F_CREATE : 0) | NLM_F_ACK,
|
||||||
}
|
nl_seq++);
|
||||||
|
nftnl_table_nlmsg_build_payload(nlh, table);
|
||||||
ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(nl), NULL, NULL);
|
|
||||||
if (ret < 0) {
|
result = send_batch(batch);
|
||||||
syslog(LOG_ERR, "%s: mnl_cb_run() FAILED: %m", "nft_send_request()");
|
}
|
||||||
return -1;
|
nftnl_table_free(table);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
/* mnl_socket_close(nl); */
|
}
|
||||||
return 0;
|
|
||||||
|
int
|
||||||
|
chain_op(enum nf_tables_msg_types op, uint16_t family, const char * table,
|
||||||
|
const char * name, const char * type, uint32_t hooknum, signed int priority )
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct mnl_nlmsg_batch *batch;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
struct nftnl_chain *chain;
|
||||||
|
|
||||||
|
log_error("(%d, %d, %s, %s, %s, %d, %d)", op, family, table, name, type, hooknum, priority);
|
||||||
|
|
||||||
|
chain = nftnl_chain_alloc();
|
||||||
|
if (chain == NULL) {
|
||||||
|
log_error("out of memory: %m");
|
||||||
|
result = -2;
|
||||||
|
} else {
|
||||||
|
nftnl_chain_set(chain, NFTNL_CHAIN_TABLE, table);
|
||||||
|
nftnl_chain_set(chain, NFTNL_CHAIN_NAME, name);
|
||||||
|
nftnl_chain_set_str(chain, NFTNL_CHAIN_TYPE, type);
|
||||||
|
nftnl_chain_set_u32(chain, NFTNL_CHAIN_HOOKNUM, hooknum);
|
||||||
|
nftnl_chain_set_s32(chain, NFTNL_CHAIN_PRIO, priority);
|
||||||
|
|
||||||
|
batch = start_batch( buf, sizeof(buf));
|
||||||
|
if (batch == NULL) {
|
||||||
|
log_error("out of memory: %m");
|
||||||
|
result = -3;
|
||||||
|
} else {
|
||||||
|
nlh = nftnl_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
|
||||||
|
op, family,
|
||||||
|
(op == NFT_MSG_NEWCHAIN ? NLM_F_CREATE : 0) | NLM_F_ACK,
|
||||||
|
nl_seq++);
|
||||||
|
if (nlh == NULL)
|
||||||
|
{
|
||||||
|
log_error("failed to build header: %m");
|
||||||
|
result = -4;
|
||||||
|
} else {
|
||||||
|
nftnl_chain_nlmsg_build_payload(nlh, chain);
|
||||||
|
|
||||||
|
result = send_batch(batch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nftnl_chain_free(chain);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct mnl_nlmsg_batch *
|
||||||
|
start_batch( char *buf, size_t buf_size)
|
||||||
|
{
|
||||||
|
struct mnl_nlmsg_batch *batch;
|
||||||
|
nl_seq = time(NULL);
|
||||||
|
|
||||||
|
if (nl == NULL) {
|
||||||
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
|
if (nl == NULL) {
|
||||||
|
log_error("mnl_socket_open() FAILED: %m");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
log_error("mnl_socket_bind() FAILED: %m");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
batch = mnl_nlmsg_batch_start(buf, buf_size);
|
||||||
|
if (batch != NULL) {
|
||||||
|
nft_mnl_batch_put(mnl_nlmsg_batch_current(batch),
|
||||||
|
NFNL_MSG_BATCH_BEGIN, nl_seq++);
|
||||||
|
mnl_nlmsg_batch_next(batch);
|
||||||
|
}
|
||||||
|
return batch;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
send_batch(struct mnl_nlmsg_batch * batch)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
mnl_nlmsg_batch_next(batch);
|
||||||
|
|
||||||
|
nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_END,
|
||||||
|
nl_seq++);
|
||||||
|
mnl_nlmsg_batch_next(batch);
|
||||||
|
|
||||||
|
if (nl == NULL) {
|
||||||
|
log_error("netlink not connected");
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch),
|
||||||
|
mnl_nlmsg_batch_size(batch));
|
||||||
|
if (ret == -1) {
|
||||||
|
log_error("mnl_socket_sendto() FAILED: %m");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_nlmsg_batch_stop(batch);
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
log_error("mnl_socket_recvfrom() FAILED: %m");
|
||||||
|
return -3;
|
||||||
|
} else if (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(nl), NULL, NULL);
|
||||||
|
if (ret == -1) {
|
||||||
|
log_error("mnl_cb_run() FAILED: %m");
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (ret > 0);
|
||||||
|
}
|
||||||
|
/* mnl_socket_close(nl); */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
finish_batch(void)
|
||||||
|
{
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
nl = NULL;
|
||||||
}
|
}
|
|
@ -8,8 +8,13 @@
|
||||||
*/
|
*/
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
|
||||||
#define NFT_TABLE_NAT "nat"
|
extern const char * nft_table;
|
||||||
#define NFT_TABLE_FILTER "filter"
|
extern const char * nft_table4;
|
||||||
|
extern const char * nft_table6;
|
||||||
|
extern const char * nft_prerouting_chain;
|
||||||
|
extern const char * nft_postrouting_chain;
|
||||||
|
extern const char * nft_forward_chain;
|
||||||
|
|
||||||
#define NFT_DESCR_SIZE 1024
|
#define NFT_DESCR_SIZE 1024
|
||||||
|
|
||||||
enum rule_reg_type {
|
enum rule_reg_type {
|
||||||
|
@ -80,7 +85,7 @@ extern struct rule_list head_redirect;
|
||||||
extern struct rule_list head_peer;
|
extern struct rule_list head_peer;
|
||||||
|
|
||||||
int
|
int
|
||||||
nft_send_request(struct nftnl_rule * rule, uint16_t cmd, enum rule_chain_type type);
|
nft_send_rule(struct nftnl_rule * rule, uint16_t cmd, enum rule_chain_type type);
|
||||||
struct nftnl_rule *
|
struct nftnl_rule *
|
||||||
rule_set_dnat(uint8_t family, const char * ifname, uint8_t proto,
|
rule_set_dnat(uint8_t family, const char * ifname, uint8_t proto,
|
||||||
in_addr_t rhost, unsigned short eport,
|
in_addr_t rhost, unsigned short eport,
|
||||||
|
@ -109,8 +114,21 @@ rule_set_filter_common(struct nftnl_rule *r, uint8_t family, const char * ifname
|
||||||
uint8_t proto, unsigned short eport, unsigned short iport,
|
uint8_t proto, unsigned short eport, unsigned short iport,
|
||||||
unsigned short rport, const char *descr, const char *handle);
|
unsigned short rport, const char *descr, const char *handle);
|
||||||
struct nftnl_rule *rule_del_handle(rule_t *r);
|
struct nftnl_rule *rule_del_handle(rule_t *r);
|
||||||
void reflesh_nft_cache_filter(void);
|
void refresh_nft_cache_filter(void);
|
||||||
void reflesh_nft_cache_redirect(void);
|
void refresh_nft_cache_redirect(void);
|
||||||
void reflesh_nft_cache_peer(void);
|
void refresh_nft_cache_peer(void);
|
||||||
void reflesh_nft_cache(struct rule_list *head, char *table, const char *chain, uint32_t family);
|
void refresh_nft_cache(struct rule_list *head, const char *table, const char *chain, uint32_t family);
|
||||||
void print_rule(rule_t *r);
|
void print_rule(rule_t *r);
|
||||||
|
|
||||||
|
int
|
||||||
|
table_op(enum nf_tables_msg_types op, uint16_t family, const char * name);
|
||||||
|
int
|
||||||
|
chain_op(enum nf_tables_msg_types op, uint16_t family, const char * table,
|
||||||
|
const char * name, const char * type, uint32_t hooknum, signed int priority );
|
||||||
|
|
||||||
|
struct mnl_nlmsg_batch *
|
||||||
|
start_batch( char *buf, size_t buf_size);
|
||||||
|
int
|
||||||
|
send_batch(struct mnl_nlmsg_batch * batch);
|
||||||
|
void
|
||||||
|
finish_batch(void);
|
||||||
|
|
|
@ -109,7 +109,7 @@ const char * queue = 0;
|
||||||
const char * tag = 0;
|
const char * tag = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_NETFILTER
|
#ifdef USE_IPTABLES
|
||||||
/* chain names to use in the nat and filter tables. */
|
/* chain names to use in the nat and filter tables. */
|
||||||
|
|
||||||
/* iptables -t nat -N MINIUPNPD
|
/* iptables -t nat -N MINIUPNPD
|
||||||
|
|
|
@ -142,7 +142,7 @@ extern const char * queue;
|
||||||
extern const char * tag;
|
extern const char * tag;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_NETFILTER
|
#ifdef USE_IPTABLES
|
||||||
extern const char * miniupnpd_nat_chain;
|
extern const char * miniupnpd_nat_chain;
|
||||||
extern const char * miniupnpd_nat_postrouting_chain;
|
extern const char * miniupnpd_nat_postrouting_chain;
|
||||||
extern const char * miniupnpd_forward_chain;
|
extern const char * miniupnpd_forward_chain;
|
||||||
|
|
Loading…
Reference in New Issue