Initial commit to support nftables.
This commit is contained in:
parent
eb72ab5330
commit
dcf218c452
|
@ -0,0 +1,228 @@
|
|||
# MiniUPnP project
|
||||
# (c) 2015 Tomofumi Hayashi
|
||||
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
# Author : Tomofumi Hayashi
|
||||
# for use with GNU Make
|
||||
#
|
||||
# options can be passed to genconfig.sh through CONFIG_OPTIONS :
|
||||
# $ CONFIG_OPTIONS="--ipv6 --igd2" make -f Makefile.linux
|
||||
#
|
||||
# To install use :
|
||||
# $ DESTDIR=/dummyinstalldir make -f Makefile.linux_nft install
|
||||
# or :
|
||||
# $ INSTALLPREFIX=/usr/local make -f Makefile.linux_nft install
|
||||
# or :
|
||||
# $ make -f Makefile.linux install
|
||||
# (default INSTALLPREFIX is /usr)
|
||||
#
|
||||
#
|
||||
CFLAGS = -O -g -DDEBUG
|
||||
CFLAGS ?= -Os
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
CFLAGS += -fno-common
|
||||
CPPFLAGS += -D_GNU_SOURCE
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wextra -Wstrict-prototypes -Wdeclaration-after-statement
|
||||
#CFLAGS += -Wno-missing-field-initializers
|
||||
CC ?= gcc
|
||||
RM = rm -f
|
||||
INSTALL = install
|
||||
STRIP ?= strip
|
||||
PKG_CONFIG ?= pkg-config
|
||||
CP = cp
|
||||
|
||||
|
||||
INSTALLPREFIX ?= $(PREFIX)/usr
|
||||
SBININSTALLDIR = $(INSTALLPREFIX)/sbin
|
||||
ETCINSTALLDIR = $(PREFIX)/etc/miniupnpd
|
||||
MANINSTALLDIR = $(INSTALLPREFIX)/share/man/man8
|
||||
|
||||
BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
|
||||
upnpreplyparse.o minixml.o portinuse.o \
|
||||
upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \
|
||||
options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \
|
||||
upnpevents.o upnputils.o getconnstatus.o \
|
||||
upnppinhole.o pcplearndscp.o asyncsendto.o
|
||||
|
||||
LNXOBJS = linux/getifstats.o linux/ifacewatcher.o linux/getroute.o
|
||||
NETFILTEROBJS = netfilter_nft/nftnlrdr.o netfilter_nft/nfct_get.o netfilter_nft/nftnlrdr_misc.o
|
||||
|
||||
ALLOBJS = $(BASEOBJS) $(LNXOBJS) $(NETFILTEROBJS)
|
||||
|
||||
PCFILE_FOUND := $(shell $(PKG_CONFIG) --exists libnftnl; echo $$?)
|
||||
|
||||
ifeq (${PCFILE_FOUND},0)
|
||||
|
||||
CFLAGS += $(shell $(PKG_CONFIG) --cflags libnftnl)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libnftnl)
|
||||
LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L libnftnl)
|
||||
LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-other libnftnl)
|
||||
else
|
||||
|
||||
ARCH ?= $(shell uname -m | grep -q "x86_64" && echo 64)
|
||||
endif # ifdef PCFILE_FOUND
|
||||
|
||||
LDLIBS += -lnfnetlink
|
||||
|
||||
TEST := $(shell $(PKG_CONFIG) --atleast-version=1.0.2 libnetfilter_conntrack && $(PKG_CONFIG) --atleast-version=1.0.3 libmnl && echo 1)
|
||||
ifeq ($(TEST),1)
|
||||
CPPFLAGS += -DUSE_NFCT
|
||||
LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libmnl)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libnetfilter_conntrack)
|
||||
endif # ($(TEST),1)
|
||||
|
||||
LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libssl)
|
||||
|
||||
TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o
|
||||
|
||||
EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \
|
||||
testupnppermissions miniupnpdctl testgetifaddr \
|
||||
testgetroute testasyncsendto testportinuse
|
||||
|
||||
.PHONY: all clean install depend genuuid
|
||||
|
||||
all: $(EXECUTABLES)
|
||||
|
||||
clean:
|
||||
$(RM) $(ALLOBJS)
|
||||
$(RM) $(EXECUTABLES)
|
||||
$(RM) testupnpdescgen.o testgetifstats.o
|
||||
$(RM) testupnppermissions.o testgetifaddr.o
|
||||
$(RM) testgetroute.o testasyncsendto.o
|
||||
$(RM) testportinuse.o
|
||||
$(RM) miniupnpdctl.o
|
||||
|
||||
install: miniupnpd miniupnpd.8 miniupnpd.conf genuuid \
|
||||
netfilter/iptables_init.sh netfilter/iptables_removeall.sh \
|
||||
netfilter/ip6tables_init.sh netfilter/ip6tables_removeall.sh \
|
||||
linux/miniupnpd.init.d.script
|
||||
$(STRIP) miniupnpd
|
||||
$(INSTALL) -d $(DESTDIR)$(SBININSTALLDIR)
|
||||
$(INSTALL) miniupnpd $(DESTDIR)$(SBININSTALLDIR)
|
||||
$(INSTALL) -d $(DESTDIR)$(ETCINSTALLDIR)
|
||||
$(INSTALL) netfilter/iptables_init.sh $(DESTDIR)$(ETCINSTALLDIR)
|
||||
$(INSTALL) netfilter/iptables_removeall.sh $(DESTDIR)$(ETCINSTALLDIR)
|
||||
$(INSTALL) netfilter/ip6tables_init.sh $(DESTDIR)$(ETCINSTALLDIR)
|
||||
$(INSTALL) netfilter/ip6tables_removeall.sh $(DESTDIR)$(ETCINSTALLDIR)
|
||||
$(INSTALL) --mode=0644 -b miniupnpd.conf $(DESTDIR)$(ETCINSTALLDIR)
|
||||
$(INSTALL) -d $(DESTDIR)$(PREFIX)/etc/init.d
|
||||
$(INSTALL) linux/miniupnpd.init.d.script $(DESTDIR)$(PREFIX)/etc/init.d/miniupnpd
|
||||
$(INSTALL) -d $(DESTDIR)$(MANINSTALLDIR)
|
||||
$(INSTALL) --mode=0644 miniupnpd.8 $(DESTDIR)$(MANINSTALLDIR)
|
||||
gzip -f $(DESTDIR)$(MANINSTALLDIR)/miniupnpd.8
|
||||
|
||||
# genuuid is using the uuidgen CLI tool which is part of libuuid
|
||||
# from the e2fsprogs
|
||||
# 'cat /proc/sys/kernel/random/uuid' could be also used
|
||||
genuuid:
|
||||
ifeq ($(TARGET_OPENWRT),)
|
||||
sed -i -e "s/^uuid=[-0-9a-f]*/uuid=`(genuuid||uuidgen||uuid) 2>/dev/null`/" miniupnpd.conf
|
||||
else
|
||||
sed -i -e "s/^uuid=[-0-9a-f]*/uuid=`($(STAGING_DIR_HOST)/bin/genuuid||$(STAGING_DIR_HOST)/bin/uuidgen||$(STAGING_DIR_HOST)/bin/uuid) 2>/dev/null`/" miniupnpd.conf
|
||||
endif
|
||||
|
||||
miniupnpd: $(BASEOBJS) $(LNXOBJS) $(NETFILTEROBJS)
|
||||
|
||||
testupnpdescgen: $(TESTUPNPDESCGENOBJS)
|
||||
|
||||
testgetifstats: testgetifstats.o linux/getifstats.o
|
||||
|
||||
testupnppermissions: testupnppermissions.o upnppermissions.o
|
||||
|
||||
testgetifaddr: testgetifaddr.o getifaddr.o
|
||||
|
||||
testgetroute: testgetroute.o linux/getroute.o upnputils.o
|
||||
|
||||
testasyncsendto: testasyncsendto.o asyncsendto.o upnputils.o \
|
||||
linux/getroute.o
|
||||
|
||||
testportinuse: testportinuse.o portinuse.o getifaddr.o \
|
||||
netfilter_nft/nftnlrdr.o netfilter_nft/nftnlrdr_misc.o
|
||||
|
||||
miniupnpdctl: miniupnpdctl.o
|
||||
|
||||
config.h: genconfig.sh VERSION
|
||||
./genconfig.sh $(CONFIG_OPTIONS)
|
||||
|
||||
depend: config.h
|
||||
makedepend -f$(MAKEFILE_LIST) -Y \
|
||||
$(ALLOBJS:.o=.c) $(TESTUPNPDESCGENOBJS:.o=.c) \
|
||||
testgetifstats.c testupnppermissions.c testgetifaddr.c \
|
||||
testgetroute.c testasyncsendto.c testportinuse.c \
|
||||
miniupnpdctl.c 2>/dev/null
|
||||
|
||||
# DO NOT DELETE
|
||||
|
||||
miniupnpd.o: config.h macros.h upnpglobalvars.h upnppermissions.h
|
||||
miniupnpd.o: miniupnpdtypes.h upnphttp.h upnpdescgen.h miniupnpdpath.h
|
||||
miniupnpd.o: getifaddr.h upnpsoap.h options.h minissdp.h upnpredirect.h
|
||||
miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h asyncsendto.h natpmp.h
|
||||
miniupnpd.o: pcpserver.h commonrdr.h upnputils.h ifacewatcher.h
|
||||
upnphttp.o: config.h upnphttp.h upnpdescgen.h miniupnpdpath.h upnpsoap.h
|
||||
upnphttp.o: upnpevents.h upnputils.h
|
||||
upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h
|
||||
upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h
|
||||
upnpdescgen.o: miniupnpdtypes.h upnpdescstrings.h upnpurns.h getconnstatus.h
|
||||
upnpsoap.o: macros.h config.h upnpglobalvars.h upnppermissions.h
|
||||
upnpsoap.o: miniupnpdtypes.h upnphttp.h upnpsoap.h upnpreplyparse.h
|
||||
upnpsoap.o: upnpredirect.h upnppinhole.h getifaddr.h getifstats.h
|
||||
upnpsoap.o: getconnstatus.h upnpurns.h
|
||||
upnpreplyparse.o: upnpreplyparse.h minixml.h
|
||||
minixml.o: minixml.h
|
||||
portinuse.o: macros.h config.h upnpglobalvars.h upnppermissions.h
|
||||
portinuse.o: miniupnpdtypes.h getifaddr.h portinuse.h netfilter_nft/nftnlrdr.h
|
||||
portinuse.o: commonrdr.h
|
||||
upnpredirect.o: macros.h config.h upnpredirect.h upnpglobalvars.h
|
||||
upnpredirect.o: upnppermissions.h miniupnpdtypes.h upnpevents.h portinuse.h
|
||||
upnpredirect.o: netfilter_nft/nftnlrdr.h commonrdr.h
|
||||
getifaddr.o: config.h getifaddr.h
|
||||
daemonize.o: daemonize.h config.h
|
||||
upnpglobalvars.o: config.h upnpglobalvars.h upnppermissions.h
|
||||
upnpglobalvars.o: miniupnpdtypes.h upnpdescstrings.h
|
||||
options.o: config.h options.h upnppermissions.h upnpglobalvars.h
|
||||
options.o: miniupnpdtypes.h
|
||||
upnppermissions.o: config.h upnppermissions.h
|
||||
minissdp.o: config.h upnpdescstrings.h miniupnpdpath.h upnphttp.h
|
||||
minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h
|
||||
minissdp.o: upnputils.h getroute.h asyncsendto.h codelength.h
|
||||
natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h
|
||||
natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h
|
||||
natpmp.o: portinuse.h asyncsendto.h
|
||||
pcpserver.o: config.h pcpserver.h macros.h upnpglobalvars.h upnppermissions.h
|
||||
pcpserver.o: miniupnpdtypes.h pcplearndscp.h upnpredirect.h commonrdr.h
|
||||
pcpserver.o: getifaddr.h asyncsendto.h pcp_msg_struct.h netfilter_nft/nftnlrdr.h
|
||||
pcpserver.o: commonrdr.h
|
||||
upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h
|
||||
upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h
|
||||
upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h
|
||||
upnputils.o: miniupnpdtypes.h getroute.h
|
||||
getconnstatus.o: getconnstatus.h getifaddr.h
|
||||
upnppinhole.o: macros.h config.h upnpredirect.h upnpglobalvars.h
|
||||
upnppinhole.o: upnppermissions.h miniupnpdtypes.h upnpevents.h
|
||||
#upnppinhole.o: netfilter/iptpinhole.h
|
||||
pcplearndscp.o: config.h upnpglobalvars.h upnppermissions.h miniupnpdtypes.h
|
||||
pcplearndscp.o: pcplearndscp.h
|
||||
asyncsendto.o: asyncsendto.h
|
||||
linux/getifstats.o: config.h getifstats.h
|
||||
linux/ifacewatcher.o: config.h ifacewatcher.h config.h minissdp.h
|
||||
linux/ifacewatcher.o: miniupnpdtypes.h getifaddr.h upnpglobalvars.h
|
||||
linux/ifacewatcher.o: upnppermissions.h natpmp.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: config.h upnpglobalvars.h upnppermissions.h
|
||||
netfilter_nft/nftnlrdr.o: miniupnpdtypes.h
|
||||
netfilter_nft/iptpinhole.o: config.h netfilter_nft/iptpinhole.h upnpglobalvars.h
|
||||
netfilter_nft/iptpinhole.o: upnppermissions.h config.h miniupnpdtypes.h
|
||||
testupnpdescgen.o: macros.h config.h upnpdescgen.h upnpdescstrings.h
|
||||
testupnpdescgen.o: getifaddr.h
|
||||
upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h
|
||||
upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h
|
||||
upnpdescgen.o: miniupnpdtypes.h upnpdescstrings.h upnpurns.h getconnstatus.h
|
||||
testgetifstats.o: getifstats.h
|
||||
testupnppermissions.o: upnppermissions.h config.h
|
||||
testgetifaddr.o: config.h getifaddr.h
|
||||
testgetroute.o: getroute.h upnputils.h upnpglobalvars.h upnppermissions.h
|
||||
testgetroute.o: config.h miniupnpdtypes.h
|
||||
testasyncsendto.o: miniupnpdtypes.h config.h upnputils.h asyncsendto.h
|
||||
testportinuse.o: macros.h config.h portinuse.h
|
||||
miniupnpdctl.o: macros.h
|
|
@ -0,0 +1,33 @@
|
|||
CFLAGS?=-Wall -g -D_GNU_SOURCE -DDEBUG -Wstrict-prototypes -Wdeclaration-after-statement
|
||||
CC = gcc
|
||||
|
||||
LIBS = -lnftnl -lmnl
|
||||
|
||||
ARCH := $(shell uname -m | grep -q "x86_64" && echo 64)
|
||||
|
||||
all: test_nfct_get testnftnlrdr
|
||||
|
||||
clean:
|
||||
$(RM) *.o testnftnlcrdr testnftnlpinhole testnftnlrdr_peer \
|
||||
test_nfct_get testnftnlrdr
|
||||
|
||||
testnftnlrdr: nftnlrdr.o nftnlrdr_misc.o testnftnlrdr.o upnpglobalvars.o $(LIBS)
|
||||
|
||||
testiptpinhole: testiptpinhole.o iptpinhole.o upnpglobalvars.o $(LIBS)
|
||||
|
||||
test_nfct_get: test_nfct_get.o test_nfct_get.o -lmnl -lnetfilter_conntrack
|
||||
|
||||
test_nfct_get.o: test_nfct_get.c
|
||||
|
||||
testnftnlrdr_peer.o: testnftnlrdr_peer.c
|
||||
|
||||
testnftnlrdr_dscp.o: testnftnlrdr_dscp.c
|
||||
|
||||
nftnlrdr.o: nftnlrdr.c nftnlrdr.h
|
||||
|
||||
nftnlrdr_misc.o: nftnlrdr_misc.c
|
||||
|
||||
iptpinhole.o: iptpinhole.c iptpinhole.h
|
||||
|
||||
upnpglobalvars.o: ../upnpglobalvars.c ../upnpglobalvars.h
|
||||
$(CC) -c -o $@ $<
|
|
@ -0,0 +1,258 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifdef USE_NFCT
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
|
||||
|
||||
#include <linux/netfilter/nf_conntrack_tcp.h>
|
||||
|
||||
struct data_cb_s
|
||||
{
|
||||
struct sockaddr_storage * ext;
|
||||
uint8_t found;
|
||||
};
|
||||
|
||||
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nf_conntrack *ct;
|
||||
struct data_cb_s * d = (struct data_cb_s*) data;
|
||||
struct sockaddr_in* ext4 = (struct sockaddr_in*) d->ext;
|
||||
|
||||
ct = nfct_new();
|
||||
if (ct == NULL)
|
||||
return MNL_CB_OK;
|
||||
nfct_nlmsg_parse(nlh, ct);
|
||||
|
||||
if (data) {
|
||||
ext4->sin_addr.s_addr = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST);
|
||||
ext4->sin_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST);
|
||||
}
|
||||
d->found = 1;
|
||||
nfct_destroy(ct);
|
||||
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto,
|
||||
struct sockaddr_storage* ret_ext)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfh;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
unsigned int seq, portid;
|
||||
struct nf_conntrack *ct;
|
||||
int ret;
|
||||
struct data_cb_s data;
|
||||
|
||||
if ((!src)&&(!dst)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (src->sa_family != dst->sa_family) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (nl == NULL) {
|
||||
// perror("mnl_socket_open");
|
||||
goto free_nl;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
// perror("mnl_socket_bind");
|
||||
goto free_nl;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
|
||||
nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
|
||||
nfh->nfgen_family = src->sa_family;
|
||||
nfh->version = NFNETLINK_V0;
|
||||
nfh->res_id = 0;
|
||||
|
||||
ct = nfct_new();
|
||||
if (ct == NULL) {
|
||||
goto free_nl;
|
||||
}
|
||||
|
||||
nfct_set_attr_u8(ct, ATTR_L3PROTO, src->sa_family);
|
||||
if (src->sa_family == AF_INET) {
|
||||
struct sockaddr_in *src4 = (struct sockaddr_in *)src;
|
||||
struct sockaddr_in *dst4 = (struct sockaddr_in *)dst;
|
||||
nfct_set_attr_u32(ct, ATTR_IPV4_SRC, src4->sin_addr.s_addr);
|
||||
nfct_set_attr_u32(ct, ATTR_IPV4_DST, dst4->sin_addr.s_addr);
|
||||
nfct_set_attr_u16(ct, ATTR_PORT_SRC, src4->sin_port);
|
||||
nfct_set_attr_u16(ct, ATTR_PORT_DST, dst4->sin_port);
|
||||
} else if (src->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)src;
|
||||
struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst;
|
||||
nfct_set_attr(ct, ATTR_IPV6_SRC, &src6->sin6_addr);
|
||||
nfct_set_attr(ct, ATTR_IPV6_DST, &dst6->sin6_addr);
|
||||
nfct_set_attr_u16(ct, ATTR_PORT_SRC, src6->sin6_port);
|
||||
nfct_set_attr_u16(ct, ATTR_PORT_DST, dst6->sin6_port);
|
||||
}
|
||||
nfct_set_attr_u8(ct, ATTR_L4PROTO, proto);
|
||||
|
||||
nfct_nlmsg_build(nlh, ct);
|
||||
|
||||
ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
|
||||
if (ret == -1) {
|
||||
goto free_ct;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
data.ext = ret_ext;
|
||||
data.found = 0;
|
||||
while (ret > 0) {
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, &data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
free_ct:
|
||||
nfct_destroy(ct);
|
||||
free_nl:
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return data.found;
|
||||
}
|
||||
|
||||
#else
|
||||
#define DST "dst="
|
||||
#define DST_PORT "dport="
|
||||
#define SRC "src="
|
||||
#define SRC_PORT "sport="
|
||||
#define IP_CONNTRACK_LOCATION "/proc/net/ip_conntrack"
|
||||
#define NF_CONNTRACK_LOCATION "/proc/net/nf_conntrack"
|
||||
|
||||
int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto,
|
||||
struct sockaddr_storage* ret_ext)
|
||||
{
|
||||
FILE *f;
|
||||
int af;
|
||||
|
||||
if (!src)
|
||||
return -2;
|
||||
|
||||
af = src->sa_family;
|
||||
|
||||
if ((f = fopen(NF_CONNTRACK_LOCATION, "r")) == NULL) {
|
||||
if ((f = fopen(IP_CONNTRACK_LOCATION, "r")) == NULL) {
|
||||
printf("could not read info about connections from the kernel, "
|
||||
"make sure netfilter is enabled in kernel or by modules.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
while (!feof(f)) {
|
||||
char line[256], *str;
|
||||
memset(line, 0, sizeof(line));
|
||||
str = fgets(line, sizeof(line), f);
|
||||
if (line[0] != 0) {
|
||||
char *token, *saveptr;
|
||||
int j;
|
||||
uint8_t src_f, src_port_f, dst_f, dst_port_f;
|
||||
src_f=src_port_f=dst_f=dst_port_f=0;
|
||||
|
||||
for (j = 1; ; j++, str = NULL) {
|
||||
token = strtok_r(str, " ", &saveptr);
|
||||
if (token == NULL)
|
||||
break;
|
||||
|
||||
if ((j==2)&&(af!=atoi(token)))
|
||||
break;
|
||||
if ((j==4)&&(proto!=atoi(token)))
|
||||
break;
|
||||
if (j<=4)
|
||||
continue;
|
||||
|
||||
if (strncmp(token, SRC, sizeof(SRC) - 1) == 0) {
|
||||
char *srcip = token + sizeof(SRC) - 1;
|
||||
uint32_t buf[4];
|
||||
memset(buf,0,sizeof(buf));
|
||||
|
||||
if (inet_pton(af, srcip, buf)!=1)
|
||||
break;
|
||||
|
||||
if (af==AF_INET) {
|
||||
struct sockaddr_in *src4=(struct sockaddr_in*)src;
|
||||
if (!src_f) {
|
||||
if (src4->sin_addr.s_addr != buf[0])
|
||||
break;
|
||||
src_f = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strncmp(token, SRC_PORT, sizeof(SRC_PORT) - 1) == 0) {
|
||||
char *src_port = token + sizeof(SRC_PORT) - 1;
|
||||
uint16_t port=atoi(src_port);
|
||||
|
||||
if (af==AF_INET) {
|
||||
struct sockaddr_in *src4=(struct sockaddr_in*)src;
|
||||
if (!src_port_f) {
|
||||
if (ntohs(src4->sin_port) != port)
|
||||
break;
|
||||
src_port_f = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(token, DST, sizeof(DST) - 1) == 0) {
|
||||
char *dstip = token + sizeof(DST) - 1;
|
||||
uint32_t buf[4];
|
||||
memset(buf,0,sizeof(buf));
|
||||
if (inet_pton(af, dstip, buf)!=1)
|
||||
break;
|
||||
if (af==AF_INET) {
|
||||
struct sockaddr_in *dst4=(struct sockaddr_in*)dst;
|
||||
if (!dst_f) {
|
||||
if (dst4->sin_addr.s_addr != buf[0])
|
||||
break;
|
||||
dst_f = 1;
|
||||
} else {
|
||||
struct sockaddr_in*ret4=(struct sockaddr_in*)ret_ext;
|
||||
ret_ext->ss_family = AF_INET;
|
||||
ret4->sin_addr.s_addr = buf[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strncmp(token, DST_PORT, sizeof(DST_PORT)-1) == 0) {
|
||||
char *dst_port = token + sizeof(DST_PORT) - 1;
|
||||
uint16_t port=atoi(dst_port);
|
||||
if (af==AF_INET) {
|
||||
struct sockaddr_in *dst4=(struct sockaddr_in*)dst;
|
||||
if (!dst_port_f) {
|
||||
if (ntohs(dst4->sin_port) != port)
|
||||
break;
|
||||
dst_port_f = 1;
|
||||
} else {
|
||||
struct sockaddr_in*ret4=(struct sockaddr_in*)ret_ext;
|
||||
ret_ext->ss_family = AF_INET;
|
||||
ret4->sin_port = htons(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (src_f && src_port_f && dst_f && dst_port_f) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,478 @@
|
|||
/*
|
||||
* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2015 Tomofumi Hayashi
|
||||
*
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <libnftnl/rule.h>
|
||||
#include <libnftnl/expr.h>
|
||||
|
||||
#include "tiny_nf_nat.h"
|
||||
|
||||
#include "../macros.h"
|
||||
#include "../config.h"
|
||||
#include "nftnlrdr.h"
|
||||
#include "../upnpglobalvars.h"
|
||||
|
||||
#include "nftnlrdr_misc.h"
|
||||
|
||||
/* dummy init and shutdown functions */
|
||||
int init_redirect(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shutdown_redirect(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
add_redirect_rule2(const char * ifname,
|
||||
const char * rhost, unsigned short eport,
|
||||
const char * iaddr, unsigned short iport, int proto,
|
||||
const char * desc, unsigned int timestamp)
|
||||
{
|
||||
struct nft_rule *r;
|
||||
UNUSED(timestamp);
|
||||
printf("add redirect rule2(%s %s %u %s %u %d %s)!\n",
|
||||
ifname, rhost, eport, iaddr, iport, proto, desc);
|
||||
r = rule_set_dnat(NFPROTO_IPV4, ifname, proto,
|
||||
0, eport,
|
||||
inet_addr(iaddr), iport, desc, NULL);
|
||||
return nft_send_request(r, NFT_MSG_NEWRULE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function submit the rule as following:
|
||||
* nft add rule nat miniupnpd-pcp-peer ip
|
||||
* saddr <iaddr> ip daddr <rhost> tcp sport <iport>
|
||||
* tcp dport <rport> snat <eaddr>:<eport>
|
||||
*/
|
||||
int
|
||||
add_peer_redirect_rule2(const char * ifname,
|
||||
const char * rhost, unsigned short rport,
|
||||
const char * eaddr, unsigned short eport,
|
||||
const char * iaddr, unsigned short iport, int proto,
|
||||
const char * desc, unsigned int timestamp)
|
||||
{
|
||||
struct nft_rule *r;
|
||||
UNUSED(ifname); UNUSED(timestamp);
|
||||
|
||||
printf("add peer redirect rule2()!\n");
|
||||
r = rule_set_snat(NFPROTO_IPV4, proto,
|
||||
inet_addr(rhost), rport,
|
||||
inet_addr(eaddr), eport,
|
||||
inet_addr(iaddr), iport, desc, NULL);
|
||||
|
||||
return nft_send_request(r, NFT_MSG_NEWRULE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function submit the rule as following:
|
||||
* nft add rule filter miniupnpd
|
||||
* ip daddr <iaddr> tcp dport <iport> accept
|
||||
*
|
||||
*/
|
||||
int
|
||||
add_filter_rule2(const char * ifname,
|
||||
const char * rhost, const char * iaddr,
|
||||
unsigned short eport, unsigned short iport,
|
||||
int proto, const char * desc)
|
||||
{
|
||||
struct nft_rule *r = NULL;
|
||||
in_addr_t rhost_addr = 0;
|
||||
if (rhost != NULL) {
|
||||
rhost_addr = inet_addr(rhost);
|
||||
}
|
||||
r = rule_set_filter(NFPROTO_IPV4, ifname, proto,
|
||||
rhost_addr, inet_addr(iaddr), eport, iport,
|
||||
desc, 0);
|
||||
return nft_send_request(r, NFT_MSG_NEWRULE);
|
||||
}
|
||||
|
||||
/*
|
||||
* add_peer_dscp_rule2() is not supported due to nft does not support
|
||||
* dscp set.
|
||||
*/
|
||||
int
|
||||
add_peer_dscp_rule2(const char * ifname,
|
||||
const char * rhost, unsigned short rport,
|
||||
unsigned char dscp,
|
||||
const char * iaddr, unsigned short iport, int proto,
|
||||
const char * desc, unsigned int timestamp)
|
||||
{
|
||||
UNUSED(ifname); UNUSED(rhost); UNUSED(rport);
|
||||
UNUSED(dscp); UNUSED(iaddr); UNUSED(iport); UNUSED(proto);
|
||||
UNUSED(desc); UNUSED(timestamp);
|
||||
syslog(LOG_ERR, "add_peer_dscp_rule2: not supported");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all rules corresponding eport/proto
|
||||
*/
|
||||
int
|
||||
delete_redirect_and_filter_rules(unsigned short eport, int proto)
|
||||
{
|
||||
rule_t *p;
|
||||
struct nft_rule *r = NULL;
|
||||
in_addr_t iaddr = 0;
|
||||
uint16_t iport = 0;
|
||||
extern void print_rule(rule_t *r) ;
|
||||
|
||||
printf("delete_redirect_and_filter_rules(%d %d)\n", eport, proto);
|
||||
reflesh_nft_cache(NFPROTO_IPV4);
|
||||
LIST_FOREACH(p, &head, entry) {
|
||||
if (p->eport == eport && p->proto == proto &&
|
||||
(p->type == RULE_NAT || p->type == RULE_SNAT)) {
|
||||
iaddr = p->iaddr;
|
||||
iport = p->iport;
|
||||
r = rule_del_handle(p);
|
||||
/* Todo: send bulk request */
|
||||
nft_send_request(r, NFT_MSG_DELRULE);
|
||||
}
|
||||
}
|
||||
|
||||
if (iaddr == 0 && iport == 0) {
|
||||
return -1;
|
||||
}
|
||||
reflesh_nft_cache(NFPROTO_IPV4);
|
||||
LIST_FOREACH(p, &head, entry) {
|
||||
if (p->eport == iport &&
|
||||
p->iaddr == iaddr && p->type == RULE_FILTER) {
|
||||
r = rule_del_handle(p);
|
||||
/* Todo: send bulk request */
|
||||
nft_send_request(r, NFT_MSG_DELRULE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* get peer by index as array.
|
||||
* return -1 when not found.
|
||||
*/
|
||||
int
|
||||
get_peer_rule_by_index(int index,
|
||||
char * ifname, unsigned short * eport,
|
||||
char * iaddr, int iaddrlen, unsigned short * iport,
|
||||
int * proto, char * desc, int desclen,
|
||||
char * rhost, int rhostlen, unsigned short * rport,
|
||||
unsigned int * timestamp,
|
||||
u_int64_t * packets, u_int64_t * bytes)
|
||||
{
|
||||
int i;
|
||||
struct in_addr addr;
|
||||
char *addr_str;
|
||||
rule_t *r;
|
||||
UNUSED(timestamp); UNUSED(packets); UNUSED(bytes);
|
||||
|
||||
printf("get_peer_rule_by_index()\n");
|
||||
reflesh_nft_cache(NFPROTO_IPV4);
|
||||
for (i = 0; peer_cache[i] != NULL; i++) {
|
||||
if (index == i) {
|
||||
r = peer_cache[i];
|
||||
if (ifname != NULL) {
|
||||
if_indextoname(r->ifidx, ifname);
|
||||
}
|
||||
if (eport != NULL) {
|
||||
*eport = r->eport;
|
||||
}
|
||||
if (iaddr != NULL) {
|
||||
addr.s_addr = r->iaddr;
|
||||
addr_str = inet_ntoa(addr);
|
||||
strncpy(iaddr , addr_str, iaddrlen);
|
||||
}
|
||||
if (iport != NULL) {
|
||||
*iport = r->iport;
|
||||
}
|
||||
if (proto != NULL) {
|
||||
*proto = r->proto;
|
||||
}
|
||||
if (rhost != NULL) {
|
||||
addr.s_addr = r->rhost;
|
||||
addr_str = inet_ntoa(addr);
|
||||
strncpy(iaddr , addr_str, rhostlen);
|
||||
}
|
||||
if (rport != NULL) {
|
||||
*rport = r->rport;
|
||||
}
|
||||
if (desc != NULL) {
|
||||
strncpy(desc, r->desc, desclen);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Implement counter in case of add {nat,filter}
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_redirect_rule()
|
||||
* returns -1 if the rule is not found
|
||||
*/
|
||||
int
|
||||
get_redirect_rule(const char * ifname, unsigned short eport, int proto,
|
||||
char * iaddr, int iaddrlen, unsigned short * iport,
|
||||
char * desc, int desclen,
|
||||
char * rhost, int rhostlen,
|
||||
unsigned int * timestamp,
|
||||
u_int64_t * packets, u_int64_t * bytes)
|
||||
{
|
||||
return get_nat_redirect_rule(NFT_TABLE_NAT,
|
||||
ifname, eport, proto,
|
||||
iaddr, iaddrlen, iport,
|
||||
desc, desclen,
|
||||
rhost, rhostlen,
|
||||
timestamp, packets, bytes);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_redirect_rule_by_index()
|
||||
* return -1 when the rule was not found
|
||||
*/
|
||||
int
|
||||
get_redirect_rule_by_index(int index,
|
||||
char * ifname, unsigned short * eport,
|
||||
char * iaddr, int iaddrlen, unsigned short * iport,
|
||||
int * proto, char * desc, int desclen,
|
||||
char * rhost, int rhostlen,
|
||||
unsigned int * timestamp,
|
||||
u_int64_t * packets, u_int64_t * bytes)
|
||||
{
|
||||
int i;
|
||||
struct in_addr addr;
|
||||
char *addr_str;
|
||||
rule_t *r;
|
||||
UNUSED(timestamp); UNUSED(packets); UNUSED(bytes);
|
||||
|
||||
printf("get_redirect_rule_by_index()\n");
|
||||
reflesh_nft_cache(NFPROTO_IPV4);
|
||||
for (i = 0; redirect_cache[i] != NULL; i++) {
|
||||
if (index == i) {
|
||||
r = redirect_cache[i];
|
||||
if (ifname != NULL) {
|
||||
if_indextoname(r->ifidx, ifname);
|
||||
}
|
||||
if (eport != NULL) {
|
||||
*eport = r->eport;
|
||||
}
|
||||
if (iaddr != NULL) {
|
||||
addr.s_addr = r->iaddr;
|
||||
addr_str = inet_ntoa(addr);
|
||||
strncpy(iaddr , addr_str, iaddrlen);
|
||||
}
|
||||
if (iport != NULL) {
|
||||
*iport = r->iport;
|
||||
}
|
||||
if (proto != NULL) {
|
||||
*proto = r->proto;
|
||||
}
|
||||
if (rhost != NULL) {
|
||||
addr.s_addr = r->rhost;
|
||||
addr_str = inet_ntoa(addr);
|
||||
strncpy(iaddr , addr_str, rhostlen);
|
||||
}
|
||||
if (desc != NULL && r->desc) {
|
||||
strncpy(desc, r->desc, desclen);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Implement counter in case of add {nat,filter}
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* return -1 not found.
|
||||
* return 0 found
|
||||
*/
|
||||
int
|
||||
get_nat_redirect_rule(const char * nat_chain_name, const char * ifname,
|
||||
unsigned short eport, int proto,
|
||||
char * iaddr, int iaddrlen, unsigned short * iport,
|
||||
char * desc, int desclen,
|
||||
char * rhost, int rhostlen,
|
||||
unsigned int * timestamp,
|
||||
u_int64_t * packets, u_int64_t * bytes)
|
||||
{
|
||||
rule_t *p;
|
||||
struct in_addr addr;
|
||||
char *addr_str;
|
||||
UNUSED(nat_chain_name);
|
||||
UNUSED(ifname);
|
||||
UNUSED(iaddrlen);
|
||||
UNUSED(timestamp);
|
||||
UNUSED(packets);
|
||||
UNUSED(bytes);
|
||||
|
||||
printf("get_nat_redirect_rule()\n");
|
||||
reflesh_nft_cache(NFPROTO_IPV4);
|
||||
|
||||
LIST_FOREACH(p, &head, entry) {
|
||||
if (p->proto == proto &&
|
||||
p->eport == eport) {
|
||||
if (p->rhost && rhost) {
|
||||
addr.s_addr = p->rhost;
|
||||
addr_str = inet_ntoa(addr);
|
||||
strncpy(iaddr , addr_str, rhostlen);
|
||||
|
||||
}
|
||||
if (desc != NULL && p->desc) {
|
||||
strncpy(desc, p->desc, desclen);
|
||||
}
|
||||
*iport = p->iport;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* return an (malloc'ed) array of "external" port for which there is
|
||||
* a port mapping. number is the size of the array
|
||||
*/
|
||||
unsigned short *
|
||||
get_portmappings_in_range(unsigned short startport, unsigned short endport,
|
||||
int proto, unsigned int * number)
|
||||
{
|
||||
uint32_t capacity;
|
||||
rule_t *p;
|
||||
unsigned short *array;
|
||||
unsigned short *tmp;
|
||||
|
||||
printf("get_portmappings_in_range()\n");
|
||||
*number = 0;
|
||||
capacity = 128;
|
||||
array = calloc(capacity, sizeof(unsigned short));
|
||||
|
||||
if (array == NULL) {
|
||||
syslog(LOG_ERR, "get_portmappings_in_range(): calloc error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LIST_FOREACH(p, &head, entry) {
|
||||
if (p->proto == proto &&
|
||||
startport <= p->eport &&
|
||||
p->eport <= endport) {
|
||||
|
||||
if (*number >= capacity) {
|
||||
tmp = realloc(array,
|
||||
sizeof(unsigned short)*capacity);
|
||||
if (tmp == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"get_portmappings_in_range(): "
|
||||
"realloc(%u) error",
|
||||
(unsigned)sizeof(unsigned short)*capacity);
|
||||
*number = 0;
|
||||
free(array);
|
||||
return NULL;
|
||||
}
|
||||
array = tmp;
|
||||
}
|
||||
array[*number] = p->eport;
|
||||
(*number)++;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/* for debug */
|
||||
/* read the "filter" and "nat" tables */
|
||||
int
|
||||
list_redirect_rule(const char * ifname)
|
||||
{
|
||||
rule_t *p;
|
||||
UNUSED(ifname);
|
||||
|
||||
reflesh_nft_cache(NFPROTO_IPV4);
|
||||
|
||||
LIST_FOREACH(p, &head, entry) {
|
||||
print_rule(p);
|
||||
}
|
||||
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* delete_rule_and_commit() :
|
||||
* subfunction used in delete_redirect_and_filter_rules() */
|
||||
static int
|
||||
delete_rule_and_commit(unsigned int index, IPTC_HANDLE h,
|
||||
const char * miniupnpd_chain,
|
||||
const char * logcaller)
|
||||
{
|
||||
/* TODO: Implement it */
|
||||
}
|
||||
|
||||
/* TODO: Implement it */
|
||||
static void
|
||||
print_iface(const char * iface, const unsigned char * mask, int invert)
|
||||
{
|
||||
unsigned i;
|
||||
if(mask[0] == 0)
|
||||
return;
|
||||
if(invert)
|
||||
printf("! ");
|
||||
for(i=0; i<IFNAMSIZ; i++)
|
||||
{
|
||||
if(mask[i])
|
||||
{
|
||||
if(iface[i])
|
||||
putchar(iface[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iface[i-1])
|
||||
putchar('+');
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
printip(uint32_t ip)
|
||||
{
|
||||
printf("%u.%u.%u.%u", ip >> 24, (ip >> 16) & 0xff,
|
||||
(ip >> 8) & 0xff, ip & 0xff);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* if 0 */
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2015 Tomofumi Hayashi
|
||||
*
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution.
|
||||
*/
|
||||
|
||||
#ifndef NFTNLRDR_H_INCLUDED
|
||||
#define NFTNLRDR_H_INCLUDED
|
||||
|
||||
#include "../commonrdr.h"
|
||||
int init_redirect(void);
|
||||
void shutdown_redirect(void);
|
||||
|
||||
int
|
||||
add_redirect_rule2(const char * ifname,
|
||||
const char * rhost, unsigned short eport,
|
||||
const char * iaddr, unsigned short iport, int proto,
|
||||
const char * desc, unsigned int timestamp);
|
||||
|
||||
int
|
||||
add_peer_redirect_rule2(const char * ifname,
|
||||
const char * rhost, unsigned short rport,
|
||||
const char * eaddr, unsigned short eport,
|
||||
const char * iaddr, unsigned short iport, int proto,
|
||||
const char * desc, unsigned int timestamp);
|
||||
|
||||
int
|
||||
add_filter_rule2(const char * ifname,
|
||||
const char * rhost, const char * iaddr,
|
||||
unsigned short eport, unsigned short iport,
|
||||
int proto, const char * desc);
|
||||
|
||||
int
|
||||
delete_redirect_and_filter_rules(unsigned short eport, int proto);
|
||||
|
||||
int
|
||||
add_peer_dscp_rule2(const char * ifname,
|
||||
const char * rhost, unsigned short rport,
|
||||
unsigned char dscp,
|
||||
const char * iaddr, unsigned short iport, int proto,
|
||||
const char * desc, unsigned int timestamp);
|
||||
|
||||
int
|
||||
get_peer_rule_by_index(int index,
|
||||
char * ifname, unsigned short * eport,
|
||||
char * iaddr, int iaddrlen, unsigned short * iport,
|
||||
int * proto, char * desc, int desclen,
|
||||
char * rhost, int rhostlen, unsigned short * rport,
|
||||
unsigned int * timestamp,
|
||||
u_int64_t * packets, u_int64_t * bytes);
|
||||
int
|
||||
get_nat_redirect_rule(const char * nat_chain_name, const char * ifname,
|
||||
unsigned short eport, int proto,
|
||||
char * iaddr, int iaddrlen, unsigned short * iport,
|
||||
char * desc, int desclen,
|
||||
char * rhost, int rhostlen,
|
||||
unsigned int * timestamp,
|
||||
u_int64_t * packets, u_int64_t * bytes);
|
||||
int
|
||||
get_redirect_rule_by_index(int index,
|
||||
char * ifname, unsigned short * eport,
|
||||
char * iaddr, int iaddrlen, unsigned short * iport,
|
||||
int * proto, char * desc, int desclen,
|
||||
char * rhost, int rhostlen,
|
||||
unsigned int * timestamp,
|
||||
u_int64_t * packets, u_int64_t * bytes);
|
||||
|
||||
unsigned short *
|
||||
get_portmappings_in_range(unsigned short startport, unsigned short endport,
|
||||
int proto, unsigned int * number);
|
||||
|
||||
/* in nfct_get.c */
|
||||
int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto,
|
||||
struct sockaddr* ret_ext);
|
||||
|
||||
/* for debug */
|
||||
int
|
||||
list_redirect_rule(const char * ifname);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2015 Tomofumi Hayashi
|
||||
*
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution.
|
||||
*/
|
||||
#include <sys/queue.h>
|
||||
|
||||
#define NFT_TABLE_NAT "nat"
|
||||
#define NFT_TABLE_FILTER "filter"
|
||||
|
||||
enum rule_reg_type {
|
||||
RULE_REG_NONE,
|
||||
RULE_REG_IIF,
|
||||
RULE_REG_IP_SRC_ADDR,
|
||||
RULE_REG_IP_DEST_ADDR,
|
||||
RULE_REG_IP_SD_ADDR, /* source & dest */
|
||||
RULE_REG_IP_PROTO,
|
||||
RULE_REG_TCP_DPORT,
|
||||
RULE_REG_TCP_SD_PORT, /* source & dest */
|
||||
RULE_REG_IMM_VAL,
|
||||
RULE_REG_MAX,
|
||||
};
|
||||
|
||||
enum rule_type {
|
||||
RULE_NONE,
|
||||
RULE_NAT,
|
||||
RULE_SNAT,
|
||||
RULE_FILTER,
|
||||
RULE_COUNTER,
|
||||
};
|
||||
|
||||
typedef struct rule_ {
|
||||
LIST_ENTRY(rule_t) entry;
|
||||
char * table;
|
||||
char * chain;
|
||||
uint64_t handle;
|
||||
enum rule_type type;
|
||||
uint32_t nat_type;
|
||||
uint32_t filter_action;
|
||||
uint32_t family;
|
||||
uint32_t ifidx;
|
||||
in_addr_t eaddr;
|
||||
in_addr_t iaddr;
|
||||
in_addr_t rhost;
|
||||
uint16_t eport;
|
||||
uint16_t iport;
|
||||
uint16_t rport;
|
||||
uint8_t proto;
|
||||
enum rule_reg_type reg1_type;
|
||||
enum rule_reg_type reg2_type;
|
||||
uint32_t reg1_val;
|
||||
uint32_t reg2_val;
|
||||
uint64_t packets;
|
||||
uint64_t bytes;
|
||||
char *desc;
|
||||
} rule_t;
|
||||
|
||||
LIST_HEAD(rule_list, rule_);
|
||||
extern struct rule_list head;
|
||||
extern rule_t **peer_cache;
|
||||
extern rule_t **redirect_cache;
|
||||
|
||||
int
|
||||
nft_send_request(struct nft_rule * rule, uint16_t cmd);
|
||||
struct nft_rule *
|
||||
rule_set_dnat(uint8_t family, const char * ifname, uint8_t proto,
|
||||
in_addr_t rhost, unsigned short eport,
|
||||
in_addr_t ihost, uint32_t iport,
|
||||
const char *descr,
|
||||
const char *handle);
|
||||
struct nft_rule *
|
||||
rule_set_snat(uint8_t family, uint8_t proto,
|
||||
in_addr_t rhost, unsigned short rport,
|
||||
in_addr_t ehost, unsigned short eport,
|
||||
in_addr_t ihost, unsigned short iport,
|
||||
const char *descr,
|
||||
const char *handle);
|
||||
struct nft_rule *
|
||||
rule_set_filter(uint8_t family, const char * ifname, uint8_t proto,
|
||||
in_addr_t rhost, in_addr_t iaddr, unsigned short eport,
|
||||
unsigned short iport, const char * descr, const char *handle);
|
||||
struct nft_rule *
|
||||
rule_del_handle(rule_t *r);
|
||||
void
|
||||
reflesh_nft_cache(uint32_t family);
|
||||
void print_rule(rule_t *r);
|
|
@ -0,0 +1,5 @@
|
|||
#! /sbin/nft -f
|
||||
|
||||
delete chain nat miniupnpd
|
||||
delete chain nat miniupnpd-pcp-peer
|
||||
delete chain filter miniupnpd
|
|
@ -0,0 +1,5 @@
|
|||
#! /sbin/nft -f
|
||||
|
||||
flush chain ip nat miniupnpd
|
||||
flush chain ip nat miniupnpd-pcp-peer
|
||||
flush chain ip filter miniupnpd
|
|
@ -0,0 +1,51 @@
|
|||
#! /bin/sh
|
||||
|
||||
nft list table nat > /dev/null
|
||||
nft_nat_exists=$?
|
||||
nft list table filter > /dev/null
|
||||
nft_filter_exists=$?
|
||||
nft list table mangle > /dev/null
|
||||
nft_mangle_exists=$?
|
||||
|
||||
if [ $nft_nat_exists -eq "1" ]; then
|
||||
echo "create nat"
|
||||
nft "add table nat"
|
||||
fi
|
||||
if [ $nft_filter_exists -eq "1" ]; then
|
||||
echo "create filter"
|
||||
nft "add table filter"
|
||||
fi
|
||||
if [ $nft_mangle_exists -eq "1" ]; then
|
||||
echo "create mangle"
|
||||
nft "add table mangle"
|
||||
fi
|
||||
|
||||
nft list chain nat miniupnpd > /dev/null
|
||||
nft_nat_miniupnpd_exists=$?
|
||||
nft list chain nat miniupnpd-pcp-peer > /dev/null
|
||||
nft_nat_miniupnpd_pcp_peer_exists=$?
|
||||
nft list chain filter miniupnpd > /dev/null
|
||||
nft_filter_miniupnpd_exists=$?
|
||||
nft list chain mangle miniupnpd > /dev/null
|
||||
nft_mangle_miniupnpd_exists=$?
|
||||
|
||||
if [ $nft_nat_miniupnpd_exists -eq "1" ]; then
|
||||
echo "create chain in nat"
|
||||
nft "add chain nat miniupnpd { \
|
||||
type nat hook prerouting priority -200 ; }"
|
||||
fi
|
||||
if [ $nft_nat_miniupnpd_pcp_peer_exists -eq "1" ]; then
|
||||
echo "create pcp peer chain in nat"
|
||||
nft "add chain nat miniupnpd-pcp-peer { \
|
||||
type nat hook postrouting priority -300 ; }"
|
||||
fi
|
||||
if [ $nft_filter_miniupnpd_exists -eq "1" ]; then
|
||||
echo "create chain in filter "
|
||||
nft "add chain filter miniupnpd { \
|
||||
type nat hook forward priority -200 ; }"
|
||||
fi
|
||||
if [ $nft_mangle_miniupnpd_exists -eq "1" ]; then
|
||||
echo "create chain in mangle"
|
||||
nft "add chain mangle miniupnpd { \
|
||||
type nat hook prerouting priority -100 ; }"
|
||||
fi
|
|
@ -0,0 +1,5 @@
|
|||
#! /sbin/nft -f
|
||||
|
||||
delete rule nat miniupnpd
|
||||
delete rule nat miniupnpd-pcp-peer
|
||||
delete rule filter miniupnpd
|
|
@ -0,0 +1,50 @@
|
|||
#include "nfct_get.c"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct sockaddr_storage src, dst, ext;
|
||||
char buff[INET6_ADDRSTRLEN];
|
||||
|
||||
if (argc!=5)
|
||||
return 0;
|
||||
|
||||
if (1 != inet_pton(AF_INET, argv[1],
|
||||
&((struct sockaddr_in*)&src)->sin_addr)) {
|
||||
if (1 != inet_pton(AF_INET6, argv[1],
|
||||
&((struct sockaddr_in6*) &src)->sin6_addr)) {
|
||||
perror("bad input param");
|
||||
} else {
|
||||
((struct sockaddr_in6*)(&src))->sin6_port = htons(atoi(argv[2]));
|
||||
src.ss_family = AF_INET6;
|
||||
}
|
||||
} else {
|
||||
((struct sockaddr_in*)(&src))->sin_port = htons(atoi(argv[2]));
|
||||
src.ss_family = AF_INET;
|
||||
}
|
||||
|
||||
if (1 != inet_pton(AF_INET, argv[3],
|
||||
&((struct sockaddr_in*)&dst)->sin_addr)) {
|
||||
if (1 != inet_pton(AF_INET6, argv[3],
|
||||
&((struct sockaddr_in6*) &dst)->sin6_addr)) {
|
||||
perror("bad input param");
|
||||
} else {
|
||||
((struct sockaddr_in6*)(&dst))->sin6_port = htons(atoi(argv[4]));
|
||||
dst.ss_family = AF_INET6;
|
||||
}
|
||||
} else {
|
||||
((struct sockaddr_in*)(&dst))->sin_port = htons(atoi(argv[4]));
|
||||
dst.ss_family = AF_INET;
|
||||
}
|
||||
|
||||
if (get_nat_ext_addr((struct sockaddr*)&src, (struct sockaddr*)&dst,
|
||||
IPPROTO_TCP, &ext)) {
|
||||
printf("Ext address %s:%d\n",
|
||||
inet_ntop(src.ss_family,
|
||||
&((struct sockaddr_in*)&ext)->sin_addr,
|
||||
buff, sizeof(buff)),
|
||||
ntohs(((struct sockaddr_in*)(&ext))->sin_port));
|
||||
} else {
|
||||
printf("no entry\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2012 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "nftnlrdr.h"
|
||||
#include "../commonrdr.h"
|
||||
|
||||
#ifndef PRIu64
|
||||
#define PRIu64 "llu"
|
||||
#endif
|
||||
|
||||
static int
|
||||
add_filter_rule(int proto, const char * rhost,
|
||||
const char * iaddr, unsigned short iport)
|
||||
{
|
||||
return add_filter_rule2(NULL, rhost, iaddr, 0, iport, proto, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
addnatrule(int proto, unsigned short eport,
|
||||
const char * iaddr, unsigned short iport,
|
||||
const char * rhost)
|
||||
{
|
||||
return add_redirect_rule2(NULL, rhost, eport, iaddr, iport, proto, NULL, 0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char ** argv)
|
||||
{
|
||||
unsigned short eport, iport;
|
||||
const char * iaddr;
|
||||
|
||||
if(argc<4) {
|
||||
printf("Usage %s <ext_port> <internal_ip> <internal_port>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
openlog("testnftnlrdr", LOG_PERROR|LOG_CONS, LOG_LOCAL0);
|
||||
eport = (unsigned short)atoi(argv[1]);
|
||||
iaddr = argv[2];
|
||||
iport = (unsigned short)atoi(argv[3]);
|
||||
printf("trying to redirect port %hu to %s:%hu\n", eport, iaddr, iport);
|
||||
if(addnatrule(IPPROTO_TCP, eport, iaddr, iport, NULL) < 0) {
|
||||
printf("addnatrule() failed!\n");
|
||||
return -1;
|
||||
}
|
||||
if(add_filter_rule(IPPROTO_TCP, NULL, iaddr, iport) < 0) {
|
||||
printf("add_filter_rule() failed!\n");
|
||||
return -1;
|
||||
}
|
||||
/* test */
|
||||
{
|
||||
unsigned short p1, p2;
|
||||
char addr[16];
|
||||
int proto2;
|
||||
char desc[256];
|
||||
char rhost[256];
|
||||
unsigned int timestamp;
|
||||
u_int64_t packets, bytes;
|
||||
|
||||
desc[0] = '\0';
|
||||
printf("test0\n");
|
||||
if(get_redirect_rule_by_index(0, "", &p1,
|
||||
addr, sizeof(addr), &p2,
|
||||
&proto2, desc, sizeof(desc),
|
||||
rhost, sizeof(rhost),
|
||||
×tamp,
|
||||
&packets, &bytes) < 0)
|
||||
{
|
||||
printf("rule not found\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("redirected port %hu to %s:%hu proto %d packets=%" PRIu64 " bytes=%" PRIu64 "\n",
|
||||
p1, addr, p2, proto2, packets, bytes);
|
||||
}
|
||||
printf("test\n");
|
||||
}
|
||||
printf("trying to list nat rules :\n");
|
||||
list_redirect_rule(argv[1]);
|
||||
printf("deleting\n");
|
||||
delete_redirect_and_filter_rules(eport, IPPROTO_TCP);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* $Id: tiny_nf_nat.h,v 1.1 2011/07/30 13:14:36 nanard Exp $ */
|
||||
/* Only what miniupnpd needs, until linux-libc-dev gains nf_nat.h */
|
||||
|
||||
#ifndef TINY_NF_NAT_H
|
||||
#define TINY_NF_NAT_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define IP_NAT_RANGE_MAP_IPS 1
|
||||
#define IP_NAT_RANGE_PROTO_SPECIFIED 2
|
||||
#define IP_NAT_RANGE_PROTO_RANDOM 4
|
||||
#define IP_NAT_RANGE_PERSISTENT 8
|
||||
|
||||
union nf_conntrack_man_proto {
|
||||
__be16 all;
|
||||
struct { __be16 port; } tcp;
|
||||
struct { __be16 port; } udp;
|
||||
struct { __be16 id; } icmp;
|
||||
struct { __be16 port; } dccp;
|
||||
struct { __be16 port; } sctp;
|
||||
struct { __be16 key; } gre;
|
||||
};
|
||||
|
||||
struct nf_nat_range {
|
||||
unsigned int flags;
|
||||
__be32 min_ip, max_ip;
|
||||
union nf_conntrack_man_proto min, max;
|
||||
};
|
||||
|
||||
struct nf_nat_multi_range_compat {
|
||||
unsigned int rangesize;
|
||||
struct nf_nat_range range[1];
|
||||
};
|
||||
|
||||
#define nf_nat_multi_range nf_nat_multi_range_compat
|
||||
|
||||
#endif /*TINY_NF_NAT_H*/
|
Loading…
Reference in New Issue