summaryrefslogtreecommitdiffstats
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--py/Makefile.am1
-rw-r--r--py/Makefile.in455
-rw-r--r--py/pyproject.toml3
-rw-r--r--py/setup.cfg24
-rwxr-xr-xpy/setup.py5
-rw-r--r--py/src/__init__.py1
-rw-r--r--py/src/nftables.py604
-rw-r--r--py/src/schema.json16
8 files changed, 1109 insertions, 0 deletions
diff --git a/py/Makefile.am b/py/Makefile.am
new file mode 100644
index 0000000..76aa082
--- /dev/null
+++ b/py/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST = pyproject.toml setup.cfg setup.py src
diff --git a/py/Makefile.in b/py/Makefile.in
new file mode 100644
index 0000000..3f7ea9e
--- /dev/null
+++ b/py/Makefile.in
@@ -0,0 +1,455 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = py
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/gcc4_visibility.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+A2X = @A2X@
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GCC_FVISIBILITY_HIDDEN = @GCC_FVISIBILITY_HIDDEN@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBMNL_CFLAGS = @LIBMNL_CFLAGS@
+LIBMNL_LIBS = @LIBMNL_LIBS@
+LIBNFTNL_CFLAGS = @LIBNFTNL_CFLAGS@
+LIBNFTNL_LIBS = @LIBNFTNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XTABLES_CFLAGS = @XTABLES_CFLAGS@
+XTABLES_LIBS = @XTABLES_LIBS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = pyproject.toml setup.cfg setup.py src
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign py/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign py/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/py/pyproject.toml b/py/pyproject.toml
new file mode 100644
index 0000000..fed528d
--- /dev/null
+++ b/py/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
diff --git a/py/setup.cfg b/py/setup.cfg
new file mode 100644
index 0000000..953b7f4
--- /dev/null
+++ b/py/setup.cfg
@@ -0,0 +1,24 @@
+[metadata]
+name = nftables
+version = attr: nftables.NFTABLES_VERSION
+description = Libnftables binding
+author = Netfilter project
+author_email = coreteam@netfilter.org
+url = https://netfilter.org/projects/nftables/index.html
+provides = nftables
+classifiers =
+ Development Status :: 4 - Beta
+ Environment :: Console
+ Intended Audience :: Developers
+ License :: OSI Approved :: GNU General Public License v2 (GPLv2)
+ Operating System :: POSIX :: Linux
+ Programming Language :: Python
+ Topic :: System :: Networking :: Firewalls
+
+[options]
+packages = nftables
+package_dir =
+ nftables = src
+
+[options.package_data]
+nftables = schema.json
diff --git a/py/setup.py b/py/setup.py
new file mode 100755
index 0000000..beda28e
--- /dev/null
+++ b/py/setup.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+from setuptools import setup
+
+setup()
diff --git a/py/src/__init__.py b/py/src/__init__.py
new file mode 100644
index 0000000..7567f09
--- /dev/null
+++ b/py/src/__init__.py
@@ -0,0 +1 @@
+from .nftables import *
diff --git a/py/src/nftables.py b/py/src/nftables.py
new file mode 100644
index 0000000..f1e43ad
--- /dev/null
+++ b/py/src/nftables.py
@@ -0,0 +1,604 @@
+#!/usr/bin/python
+# Copyright(C) 2018 Phil Sutter <phil@nwl.cc>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import json
+from ctypes import *
+import sys
+import os
+
+NFTABLES_VERSION = "0.1"
+
+class SchemaValidator:
+ """Libnftables JSON validator using jsonschema"""
+
+ def __init__(self):
+ schema_path = os.path.join(os.path.dirname(__file__), "schema.json")
+ with open(schema_path, 'r') as schema_file:
+ self.schema = json.load(schema_file)
+ import jsonschema
+ self.jsonschema = jsonschema
+
+ def validate(self, json):
+ self.jsonschema.validate(instance=json, schema=self.schema)
+
+class Nftables:
+ """A class representing libnftables interface"""
+
+ input_flags = {
+ "no-dns": 0x1,
+ "json": 0x2,
+ }
+
+ debug_flags = {
+ "scanner": 0x1,
+ "parser": 0x2,
+ "eval": 0x4,
+ "netlink": 0x8,
+ "mnl": 0x10,
+ "proto-ctx": 0x20,
+ "segtree": 0x40,
+ }
+
+ output_flags = {
+ "reversedns": (1 << 0),
+ "service": (1 << 1),
+ "stateless": (1 << 2),
+ "handle": (1 << 3),
+ "json": (1 << 4),
+ "echo": (1 << 5),
+ "guid": (1 << 6),
+ "numeric_proto": (1 << 7),
+ "numeric_prio": (1 << 8),
+ "numeric_symbol": (1 << 9),
+ "numeric_time": (1 << 10),
+ "terse": (1 << 11),
+ }
+
+ validator = None
+
+ def __init__(self, sofile="libnftables.so.1"):
+ """Instantiate a new Nftables class object.
+
+ Accepts a shared object file to open, by default standard search path
+ is searched for a file named 'libnftables.so'.
+
+ After loading the library using ctypes module, a new nftables context
+ is requested from the library and buffering of output and error streams
+ is turned on.
+ """
+ self.__ctx = None
+
+ lib = cdll.LoadLibrary(sofile)
+
+ ### API function definitions
+
+ self.nft_ctx_new = lib.nft_ctx_new
+ self.nft_ctx_new.restype = c_void_p
+ self.nft_ctx_new.argtypes = [c_int]
+
+ self.nft_ctx_input_get_flags = lib.nft_ctx_input_get_flags
+ self.nft_ctx_input_get_flags.restype = c_uint
+ self.nft_ctx_input_get_flags.argtypes = [c_void_p]
+
+ self.nft_ctx_input_set_flags = lib.nft_ctx_input_set_flags
+ self.nft_ctx_input_set_flags.restype = c_uint
+ self.nft_ctx_input_set_flags.argtypes = [c_void_p, c_uint]
+
+ self.nft_ctx_output_get_flags = lib.nft_ctx_output_get_flags
+ self.nft_ctx_output_get_flags.restype = c_uint
+ self.nft_ctx_output_get_flags.argtypes = [c_void_p]
+
+ self.nft_ctx_output_set_flags = lib.nft_ctx_output_set_flags
+ self.nft_ctx_output_set_flags.argtypes = [c_void_p, c_uint]
+
+ self.nft_ctx_output_get_debug = lib.nft_ctx_output_get_debug
+ self.nft_ctx_output_get_debug.restype = c_int
+ self.nft_ctx_output_get_debug.argtypes = [c_void_p]
+
+ self.nft_ctx_output_set_debug = lib.nft_ctx_output_set_debug
+ self.nft_ctx_output_set_debug.argtypes = [c_void_p, c_int]
+
+ self.nft_ctx_buffer_output = lib.nft_ctx_buffer_output
+ self.nft_ctx_buffer_output.restype = c_int
+ self.nft_ctx_buffer_output.argtypes = [c_void_p]
+
+ self.nft_ctx_get_output_buffer = lib.nft_ctx_get_output_buffer
+ self.nft_ctx_get_output_buffer.restype = c_char_p
+ self.nft_ctx_get_output_buffer.argtypes = [c_void_p]
+
+ self.nft_ctx_buffer_error = lib.nft_ctx_buffer_error
+ self.nft_ctx_buffer_error.restype = c_int
+ self.nft_ctx_buffer_error.argtypes = [c_void_p]
+
+ self.nft_ctx_get_error_buffer = lib.nft_ctx_get_error_buffer
+ self.nft_ctx_get_error_buffer.restype = c_char_p
+ self.nft_ctx_get_error_buffer.argtypes = [c_void_p]
+
+ self.nft_run_cmd_from_buffer = lib.nft_run_cmd_from_buffer
+ self.nft_run_cmd_from_buffer.restype = c_int
+ self.nft_run_cmd_from_buffer.argtypes = [c_void_p, c_char_p]
+
+ self.nft_run_cmd_from_filename = lib.nft_run_cmd_from_filename
+ self.nft_run_cmd_from_filename.restype = c_int
+ self.nft_run_cmd_from_filename.argtypes = [c_void_p, c_char_p]
+
+ self.nft_ctx_add_include_path = lib.nft_ctx_add_include_path
+ self.nft_ctx_add_include_path.restype = c_int
+ self.nft_ctx_add_include_path.argtypes = [c_void_p, c_char_p]
+
+ self.nft_ctx_clear_include_paths = lib.nft_ctx_clear_include_paths
+ self.nft_ctx_clear_include_paths.argtypes = [c_void_p]
+
+ self.nft_ctx_get_dry_run = lib.nft_ctx_get_dry_run
+ self.nft_ctx_get_dry_run.restype = c_bool
+ self.nft_ctx_get_dry_run.argtypes = [c_void_p]
+
+ self.nft_ctx_set_dry_run = lib.nft_ctx_set_dry_run
+ self.nft_ctx_set_dry_run.argtypes = [c_void_p, c_bool]
+
+ self.nft_ctx_add_var = lib.nft_ctx_add_var
+ self.nft_ctx_add_var.restype = c_int
+ self.nft_ctx_add_var.argtypes = [c_void_p, c_char_p]
+
+ self.nft_ctx_clear_vars = lib.nft_ctx_clear_vars
+ self.nft_ctx_clear_vars.argtypes = [c_void_p]
+
+ self.nft_ctx_free = lib.nft_ctx_free
+ lib.nft_ctx_free.argtypes = [c_void_p]
+
+ # initialize libnftables context
+ self.__ctx = self.nft_ctx_new(0)
+ self.nft_ctx_buffer_output(self.__ctx)
+ self.nft_ctx_buffer_error(self.__ctx)
+
+ def __del__(self):
+ if self.__ctx is not None:
+ self.nft_ctx_free(self.__ctx)
+ self.__ctx = None
+
+ def _flags_from_numeric(self, flags_dict, val):
+ names = []
+ for n, v in flags_dict.items():
+ if val & v:
+ names.append(n)
+ val &= ~v
+ if val:
+ names.append(val)
+ return names
+
+ def _flags_to_numeric(self, flags_dict, values):
+ if isinstance(values, (str, int)):
+ values = (values,)
+
+ val = 0
+ for v in values:
+ if isinstance(v, str):
+ v = flags_dict.get(v)
+ if v is None:
+ raise ValueError("Invalid argument")
+ elif isinstance(v, int):
+ if v < 0 or v > 0xFFFFFFFF:
+ raise ValueError("Invalid argument")
+ else:
+ raise TypeError("Not a valid flag")
+ val |= v
+
+ return val
+
+ def get_input_flags(self):
+ """Get currently active input flags.
+
+ Returns a set of flag names. See set_input_flags() for details.
+ """
+ val = self.nft_ctx_input_get_flags(self.__ctx)
+ return self._flags_from_numeric(self.input_flags, val)
+
+ def set_input_flags(self, values):
+ """Set input flags.
+
+ Resets all input flags to values. Accepts either a single flag or a list
+ of flags. Each flag might be given either as string or integer value as
+ shown in the following table:
+
+ Name | Value (hex)
+ -----------------------
+ "no-dns" | 0x1
+ "json" | 0x2
+
+ "no-dns" disables blocking address lookup.
+ "json" enables JSON mode for input.
+
+ Returns a set of previously active input flags, as returned by
+ get_input_flags() method.
+ """
+ val = self._flags_to_numeric(self.input_flags, values)
+ old = self.nft_ctx_input_set_flags(self.__ctx, val)
+ return self._flags_from_numeric(self.input_flags, old)
+
+ def __get_output_flag(self, name):
+ flag = self.output_flags[name]
+ return (self.nft_ctx_output_get_flags(self.__ctx) & flag) != 0
+
+ def __set_output_flag(self, name, val):
+ flag = self.output_flags[name]
+ flags = self.nft_ctx_output_get_flags(self.__ctx)
+ if val:
+ new_flags = flags | flag
+ else:
+ new_flags = flags & ~flag
+ self.nft_ctx_output_set_flags(self.__ctx, new_flags)
+ return (flags & flag) != 0
+
+ def get_reversedns_output(self):
+ """Get the current state of reverse DNS output.
+
+ Returns a boolean indicating whether reverse DNS lookups are performed
+ for IP addresses in output.
+ """
+ return self.__get_output_flag("reversedns")
+
+ def set_reversedns_output(self, val):
+ """Enable or disable reverse DNS output.
+
+ Accepts a boolean turning reverse DNS lookups in output on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("reversedns", val)
+
+ def get_service_output(self):
+ """Get the current state of service name output.
+
+ Returns a boolean indicating whether service names are used for port
+ numbers in output or not.
+ """
+ return self.__get_output_flag("service")
+
+ def set_service_output(self, val):
+ """Enable or disable service name output.
+
+ Accepts a boolean turning service names for port numbers in output on
+ or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("service", val)
+
+ def get_stateless_output(self):
+ """Get the current state of stateless output.
+
+ Returns a boolean indicating whether stateless output is active or not.
+ """
+ return self.__get_output_flag("stateless")
+
+ def set_stateless_output(self, val):
+ """Enable or disable stateless output.
+
+ Accepts a boolean turning stateless output either on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("stateless", val)
+
+ def get_handle_output(self):
+ """Get the current state of handle output.
+
+ Returns a boolean indicating whether handle output is active or not.
+ """
+ return self.__get_output_flag("handle")
+
+ def set_handle_output(self, val):
+ """Enable or disable handle output.
+
+ Accepts a boolean turning handle output on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("handle", val)
+
+ def get_json_output(self):
+ """Get the current state of JSON output.
+
+ Returns a boolean indicating whether JSON output is active or not.
+ """
+ return self.__get_output_flag("json")
+
+ def set_json_output(self, val):
+ """Enable or disable JSON output.
+
+ Accepts a boolean turning JSON output either on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("json", val)
+
+ def get_echo_output(self):
+ """Get the current state of echo output.
+
+ Returns a boolean indicating whether echo output is active or not.
+ """
+ return self.__get_output_flag("echo")
+
+ def set_echo_output(self, val):
+ """Enable or disable echo output.
+
+ Accepts a boolean turning echo output on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("echo", val)
+
+ def get_guid_output(self):
+ """Get the current state of GID/UID output.
+
+ Returns a boolean indicating whether names for group/user IDs are used
+ in output or not.
+ """
+ return self.__get_output_flag("guid")
+
+ def set_guid_output(self, val):
+ """Enable or disable GID/UID output.
+
+ Accepts a boolean turning names for group/user IDs on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("guid", val)
+
+ def get_numeric_proto_output(self):
+ """Get current status of numeric protocol output flag.
+
+ Returns a boolean value indicating the status.
+ """
+ return self.__get_output_flag("numeric_proto")
+
+ def set_numeric_proto_output(self, val):
+ """Set numeric protocol output flag.
+
+ Accepts a boolean turning numeric protocol output either on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("numeric_proto", val)
+
+ def get_numeric_prio_output(self):
+ """Get current status of numeric chain priority output flag.
+
+ Returns a boolean value indicating the status.
+ """
+ return self.__get_output_flag("numeric_prio")
+
+ def set_numeric_prio_output(self, val):
+ """Set numeric chain priority output flag.
+
+ Accepts a boolean turning numeric chain priority output either on or
+ off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("numeric_prio", val)
+
+ def get_numeric_symbol_output(self):
+ """Get current status of numeric symbols output flag.
+
+ Returns a boolean value indicating the status.
+ """
+ return self.__get_output_flag("numeric_symbol")
+
+ def set_numeric_symbol_output(self, val):
+ """Set numeric symbols output flag.
+
+ Accepts a boolean turning numeric representation of symbolic constants
+ in output either on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("numeric_symbol", val)
+
+ def get_numeric_time_output(self):
+ """Get current status of numeric times output flag.
+
+ Returns a boolean value indicating the status.
+ """
+ return self.__get_output_flag("numeric_time")
+
+ def set_numeric_time_output(self, val):
+ """Set numeric times output flag.
+
+ Accepts a boolean turning numeric representation of time values
+ in output either on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("numeric_time", val)
+
+ def get_terse_output(self):
+ """Get the current state of terse output.
+
+ Returns a boolean indicating whether terse output is active or not.
+ """
+ return self.__get_output_flag("terse")
+
+ def set_terse_output(self, val):
+ """Enable or disable terse output.
+
+ Accepts a boolean turning terse output either on or off.
+
+ Returns the previous value.
+ """
+ return self.__set_output_flag("terse", val)
+
+ def get_debug(self):
+ """Get currently active debug flags.
+
+ Returns a set of flag names. See set_debug() for details.
+ """
+ val = self.nft_ctx_output_get_debug(self.__ctx)
+ return self._flags_from_numeric(self.debug_flags, val)
+
+ def set_debug(self, values):
+ """Set debug output flags.
+
+ Accepts either a single flag or a set of flags. Each flag might be
+ given either as string or integer value as shown in the following
+ table:
+
+ Name | Value (hex)
+ -----------------------
+ scanner | 0x1
+ parser | 0x2
+ eval | 0x4
+ netlink | 0x8
+ mnl | 0x10
+ proto-ctx | 0x20
+ segtree | 0x40
+
+ Returns a set of previously active debug flags, as returned by
+ get_debug() method.
+ """
+ val = self._flags_to_numeric(self.debug_flags, values)
+ old = self.get_debug()
+ self.nft_ctx_output_set_debug(self.__ctx, val)
+ return old
+
+ def cmd(self, cmdline):
+ """Run a simple nftables command via libnftables.
+
+ Accepts a string containing an nftables command just like what one
+ would enter into an interactive nftables (nft -i) session.
+
+ Returns a tuple (rc, output, error):
+ rc -- return code as returned by nft_run_cmd_from_buffer() fuction
+ output -- a string containing output written to stdout
+ error -- a string containing output written to stderr
+ """
+ cmdline_is_unicode = False
+ if not isinstance(cmdline, bytes):
+ cmdline_is_unicode = True
+ cmdline = cmdline.encode("utf-8")
+ rc = self.nft_run_cmd_from_buffer(self.__ctx, cmdline)
+ output = self.nft_ctx_get_output_buffer(self.__ctx)
+ error = self.nft_ctx_get_error_buffer(self.__ctx)
+ if cmdline_is_unicode:
+ output = output.decode("utf-8")
+ error = error.decode("utf-8")
+
+ return (rc, output, error)
+
+ def json_cmd(self, json_root):
+ """Run an nftables command in JSON syntax via libnftables.
+
+ Accepts a hash object as input.
+
+ Returns a tuple (rc, output, error):
+ rc -- return code as returned by nft_run_cmd_from_buffer() function
+ output -- a hash object containing library standard output
+ error -- a string containing output written to stderr
+ """
+ json_out_old = self.set_json_output(True)
+ rc, output, error = self.cmd(json.dumps(json_root))
+ if not json_out_old:
+ self.set_json_output(json_out_old)
+ if len(output):
+ output = json.loads(output)
+ return (rc, output, error)
+
+ def json_validate(self, json_root):
+ """Validate JSON object against libnftables schema.
+
+ Accepts a hash object as input.
+
+ Returns True if JSON is valid, raises an exception otherwise.
+ """
+ if not self.validator:
+ self.validator = SchemaValidator()
+
+ self.validator.validate(json_root)
+ return True
+
+ def cmd_from_file(self, filename):
+ """Run a nftables command set from a file
+
+ filename can be a str or a Path
+
+ Returns a tuple (rc, output, error):
+ rc -- return code as returned by nft_run_cmd_from_filename() function
+ output -- a string containing output written to stdout
+ error -- a string containing output written to stderr
+ """
+ filename_is_unicode = False
+ if not isinstance(filename, bytes):
+ filename_is_unicode = True
+ filename = str(filename)
+ filename= filename.encode("utf-8")
+ rc = self.nft_run_cmd_from_filename(self.__ctx, filename)
+ output = self.nft_ctx_get_output_buffer(self.__ctx)
+ error = self.nft_ctx_get_error_buffer(self.__ctx)
+ if filename_is_unicode:
+ output = output.decode("utf-8")
+ error = error.decode("utf-8")
+ return (rc, output, error)
+
+ def add_include_path(self, filename):
+ """Add a path to the include file list
+ The default list includes the built-in default one
+
+ Returns True on success, False if memory allocation fails
+ """
+ if not isinstance(filename, bytes):
+ filename = str(filename)
+ filename= filename.encode("utf-8")
+ rc = self.nft_ctx_add_include_path(self.__ctx, filename)
+ return rc == 0
+
+ def clear_include_paths(self):
+ """Clear include path list
+
+ Will also remove the built-in default one
+ """
+ self.nft_ctx_clear_include_paths(self.__ctx)
+
+ def get_dry_run(self):
+ """Get dry run state
+
+ Returns True if set, False otherwise
+ """
+ return self.nft_ctx_get_dry_run(self.__ctx)
+
+ def set_dry_run(self, onoff):
+ """ Set dry run state
+
+ Returns the previous dry run state
+ """
+ old = self.get_dry_run()
+ self.nft_ctx_set_dry_run(self.__ctx, onoff)
+
+ return old
+
+ def add_var(self, var):
+ """Add a variable to the variable list
+
+ Returns True if added, False otherwise
+ """
+ if not isinstance(var, bytes):
+ var = var.encode("utf-8")
+ rc = self.nft_ctx_add_var(self.__ctx, var)
+ return rc == 0
+
+ def clear_vars(self):
+ """Clear variable list
+ """
+ self.nft_ctx_clear_vars(self.__ctx)
diff --git a/py/src/schema.json b/py/src/schema.json
new file mode 100644
index 0000000..460e215
--- /dev/null
+++ b/py/src/schema.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "http://json-schema.org/schema#",
+ "description": "libnftables JSON API schema",
+
+ "type": "object",
+ "properties": {
+ "nftables": {
+ "type": "array",
+ "minitems": 0,
+ "items": {
+ "type": "object"
+ }
+ }
+ },
+ "required": [ "nftables" ]
+}