From 0d6ed0e836f624ca4f73d43f10c8ca72e9fe70d1 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 31 Oct 2018 13:53:16 +0100 Subject: py: Adjust Nftables class to output flags changes Introduce setter/getter methods for each introduced output flag. Ignore NFT_CTX_OUTPUT_NUMERIC_ALL for now since it's main purpose is for internal use. Adjust the script in tests/py accordingly: Due to the good defaults, only numeric proto output has to be selected - this is not a must, but allows for the test cases to remain unchanged. Signed-off-by: Phil Sutter Signed-off-by: Pablo Neira Ayuso --- py/nftables.py | 220 +++++++++++++++++++++++++++++++++------------------ tests/py/nft-test.py | 29 +++---- 2 files changed, 153 insertions(+), 96 deletions(-) diff --git a/py/nftables.py b/py/nftables.py index d85bbb2f..6891cb1c 100644 --- a/py/nftables.py +++ b/py/nftables.py @@ -33,11 +33,17 @@ class Nftables: "segtree": 0x40, } - numeric_levels = { - "none": 0, - "addr": 1, - "port": 2, - "all": 3, + 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), } def __init__(self, sofile="libnftables.so"): @@ -58,40 +64,12 @@ class Nftables: self.nft_ctx_new.restype = c_void_p self.nft_ctx_new.argtypes = [c_int] - self.nft_ctx_output_get_handle = lib.nft_ctx_output_get_handle - self.nft_ctx_output_get_handle.restype = c_bool - self.nft_ctx_output_get_handle.argtypes = [c_void_p] + 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_handle = lib.nft_ctx_output_set_handle - self.nft_ctx_output_set_handle.argtypes = [c_void_p, c_bool] - - self.nft_ctx_output_get_echo = lib.nft_ctx_output_get_echo - self.nft_ctx_output_get_echo.restype = c_bool - self.nft_ctx_output_get_echo.argtypes = [c_void_p] - - self.nft_ctx_output_set_echo = lib.nft_ctx_output_set_echo - self.nft_ctx_output_set_echo.argtypes = [c_void_p, c_bool] - - self.nft_ctx_output_get_numeric = lib.nft_ctx_output_get_numeric - self.nft_ctx_output_get_numeric.restype = c_int - self.nft_ctx_output_get_numeric.argtypes = [c_void_p] - - self.nft_ctx_output_set_numeric = lib.nft_ctx_output_set_numeric - self.nft_ctx_output_set_numeric.argtypes = [c_void_p, c_int] - - self.nft_ctx_output_get_stateless = lib.nft_ctx_output_get_stateless - self.nft_ctx_output_get_stateless.restype = c_bool - self.nft_ctx_output_get_stateless.argtypes = [c_void_p] - - self.nft_ctx_output_set_stateless = lib.nft_ctx_output_set_stateless - self.nft_ctx_output_set_stateless.argtypes = [c_void_p, c_bool] - - self.nft_ctx_output_get_json = lib.nft_ctx_output_get_json - self.nft_ctx_output_get_json.restype = c_bool - self.nft_ctx_output_get_json.argtypes = [c_void_p] - - self.nft_ctx_output_set_json = lib.nft_ctx_output_set_json - self.nft_ctx_output_set_json.argtypes = [c_void_p, c_bool] + 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 @@ -128,12 +106,77 @@ class Nftables: self.nft_ctx_buffer_output(self.__ctx) self.nft_ctx_buffer_error(self.__ctx) + def __get_output_flag(self, name): + flag = self.output_flags[name] + return self.nft_ctx_output_get_flags(self.__ctx) & flag + + 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 + + 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.nft_ctx_output_get_handle(self.__ctx) + return self.__get_output_flag("handle") def set_handle_output(self, val): """Enable or disable handle output. @@ -142,16 +185,30 @@ class Nftables: Returns the previous value. """ - old = self.get_handle_output() - self.nft_ctx_output_set_handle(self.__ctx, val) - return old + 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.nft_ctx_output_get_echo(self.__ctx) + return self.__get_output_flag("echo") def set_echo_output(self, val): """Enable or disable echo output. @@ -160,67 +217,74 @@ class Nftables: Returns the previous value. """ - old = self.get_echo_output() - self.nft_ctx_output_set_echo(self.__ctx, val) - return old + return self.__set_output_flag("echo", val) - def get_numeric_output(self): - """Get the current state of numeric output. + def get_guid_output(self): + """Get the current state of GID/UID output. - Returns a boolean indicating whether boolean output is active or not. + Returns a boolean indicating whether names for group/user IDs are used + in output or not. """ - return self.nft_ctx_output_get_numeric(self.__ctx) + return self.__get_output_flag("guid") - def set_numeric_output(self, val): - """Enable or disable numeric output. + def set_guid_output(self, val): + """Enable or disable GID/UID output. - Accepts a boolean turning numeric output on or off. + Accepts a boolean turning names for group/user IDs on or off. Returns the previous value. """ - old = self.get_numeric_output() + return self.__set_output_flag("guid", val) - if type(val) is str: - val = self.numeric_levels[val] - self.nft_ctx_output_set_numeric(self.__ctx, val) + def get_numeric_proto_output(self): + """Get current status of numeric protocol output flag. - return old + Returns a boolean value indicating the status. + """ + return self.__get_output_flag("numeric_proto") - def get_stateless_output(self): - """Get the current state of stateless output. + def set_numeric_proto_output(self, val): + """Set numeric protocol output flag. - Returns a boolean indicating whether stateless output is active or not. + Accepts a boolean turning numeric protocol output either on or off. + + Returns the previous value. """ - return self.nft_ctx_output_get_stateless(self.__ctx) + return self.__set_output_flag("numeric_proto", val) - def set_stateless_output(self, val): - """Enable or disable stateless output. + def get_numeric_prio_output(self): + """Get current status of numeric chain priority output flag. - Accepts a boolean turning stateless output either on or off. + 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. """ - old = self.get_stateless_output() - self.nft_ctx_output_set_stateless(self.__ctx, val) - return old + return self.__set_output_flag("numeric_prio", val) - def get_json_output(self): - """Get the current state of JSON output. + def get_numeric_symbol_output(self): + """Get current status of numeric symbols output flag. - Returns a boolean indicating whether JSON output is active or not. + Returns a boolean value indicating the status. """ - return self.nft_ctx_output_get_json(self.__ctx) + return self.__get_output_flag("numeric_symbol") - def set_json_output(self, val): - """Enable or disable JSON output. + def set_numeric_symbol_output(self, val): + """Set numeric symbols output flag. - Accepts a boolean turning JSON output either on or off. + Accepts a boolean turning numeric representation of symbolic constants + in output either on or off. Returns the previous value. """ - old = self.get_json_output() - self.nft_ctx_output_set_json(self.__ctx, val) - return old + return self.__set_output_flag("numeric_symbol", val) def get_debug(self): """Get currently active debug flags. diff --git a/tests/py/nft-test.py b/tests/py/nft-test.py index 1837c9c9..5c7e28a0 100755 --- a/tests/py/nft-test.py +++ b/tests/py/nft-test.py @@ -176,7 +176,7 @@ def table_exist(table, filename, lineno): Exists a table. ''' cmd = "list table %s" % table - ret = execute_cmd(cmd, filename, lineno, numeric="all") + ret = execute_cmd(cmd, filename, lineno) return True if (ret == 0) else False @@ -263,7 +263,7 @@ def chain_exist(chain, table, filename): Checks a chain ''' cmd = "list chain %s %s" % (table, chain) - ret = execute_cmd(cmd, filename, chain.lineno, numeric="all") + ret = execute_cmd(cmd, filename, chain.lineno) return True if (ret == 0) else False @@ -466,7 +466,7 @@ def set_exist(set_name, table, filename, lineno): Check if the set exists. ''' cmd = "list set %s %s" % (table, set_name) - ret = execute_cmd(cmd, filename, lineno, numeric="all") + ret = execute_cmd(cmd, filename, lineno) return True if (ret == 0) else False @@ -476,7 +476,7 @@ def _set_exist(s, filename, lineno): Check if the set exists. ''' cmd = "list set %s %s %s" % (s.family, s.table, s.name) - ret = execute_cmd(cmd, filename, lineno, numeric="all") + ret = execute_cmd(cmd, filename, lineno) return True if (ret == 0) else False @@ -584,7 +584,7 @@ def obj_exist(o, table, filename, lineno): Check if the object exists. ''' cmd = "list %s %s %s" % (o.type, table, o.name) - ret = execute_cmd(cmd, filename, lineno, numeric="all") + ret = execute_cmd(cmd, filename, lineno) return True if (ret == 0) else False @@ -594,7 +594,7 @@ def _obj_exist(o, filename, lineno): Check if the object exists. ''' cmd = "list %s %s %s %s" % (o.type, o.family, o.table, o.name) - ret = execute_cmd(cmd, filename, lineno, numeric="all") + ret = execute_cmd(cmd, filename, lineno) return True if (ret == 0) else False @@ -805,11 +805,11 @@ def rule_add(rule, filename, lineno, force_all_family_option, filename_path): gotf.name, 1) # Check for matching ruleset listing - numeric_old = nftables.set_numeric_output("all") + numeric_proto_old = nftables.set_numeric_proto_output(True) stateless_old = nftables.set_stateless_output(True) list_cmd = 'list table %s' % table rc, pre_output, err = nftables.cmd(list_cmd) - nftables.set_numeric_output(numeric_old) + nftables.set_numeric_proto_output(numeric_proto_old) nftables.set_stateless_output(stateless_old) output = pre_output.split(";") @@ -937,12 +937,12 @@ def rule_add(rule, filename, lineno, force_all_family_option, filename_path): gotf.name, 1) # Check for matching ruleset listing - numeric_old = nftables.set_numeric_output("all") + numeric_proto_old = nftables.set_numeric_proto_output(True) stateless_old = nftables.set_stateless_output(True) json_old = nftables.set_json_output(True) rc, json_output, err = nftables.cmd(list_cmd) nftables.set_json_output(json_old) - nftables.set_numeric_output(numeric_old) + nftables.set_numeric_proto_output(numeric_proto_old) nftables.set_stateless_output(stateless_old) json_output = json.loads(json_output) @@ -990,8 +990,7 @@ def signal_handler(signal, frame): signal_received = 1 -def execute_cmd(cmd, filename, lineno, - stdout_log=False, numeric=False, debug=False): +def execute_cmd(cmd, filename, lineno, stdout_log=False, debug=False): ''' Executes a command, checks for segfaults and returns the command exit code. @@ -1000,7 +999,6 @@ def execute_cmd(cmd, filename, lineno, :param filename: name of the file tested (used for print_error purposes) :param lineno: line number being tested (used for print_error purposes) :param stdout_log: redirect stdout to this file instead of global log_file - :param numeric: turn numeric output temporarily on :param debug: temporarily set these debug flags ''' global log_file @@ -1008,9 +1006,6 @@ def execute_cmd(cmd, filename, lineno, if debug_option: print cmd - if numeric: - numeric_old = nftables.get_numeric_output() - nftables.set_numeric_output(numeric) if debug: debug_old = nftables.get_debug() nftables.set_debug(debug) @@ -1025,8 +1020,6 @@ def execute_cmd(cmd, filename, lineno, log_file.write(err) log_file.flush() - if numeric: - nftables.set_numeric_output(numeric_old) if debug: nftables.set_debug(debug_old) -- cgit v1.2.3