* Wed Jul 22 2026 Phil Sutter <psutter@redhat.com> [1.0.9-8.el9]
- spec: Update expected test suite results (Phil Sutter) [RHEL-190549]
- tests: monitor: Fix for out-of-path call (Phil Sutter) [RHEL-190549]
- tests: monitor: Excercise all syntaxes and variants by default (Phil Sutter) [RHEL-190549]
- tests: monitor: Test JSON echo mode as well (Phil Sutter) [RHEL-190549]
- tests: monitor: Become $PWD agnostic (Phil Sutter) [RHEL-190549]
- tests: monitor: Run in own netns (Phil Sutter) [RHEL-190549]
- tests: monitor: Label diffs to help users (Phil Sutter) [RHEL-190549]
- tests: monitor: Extend testcases a bit (Phil Sutter) [RHEL-190549]
- tests: monitor: enclose device names in quotes (Phil Sutter) [RHEL-190549]
- json: Dump flowtable hook spec only if present (Phil Sutter) [RHEL-190549]
- tests: py: Fix some JSON equivalents (Phil Sutter) [RHEL-190549]
- rule: constify set_is_non_concat_range() (Phil Sutter) [RHEL-190549]
- datatype: don't return a const string from cgroupv2_get_path() (Phil Sutter) [RHEL-190549]
- tests: py: Fix --keep test runner option (Phil Sutter) [RHEL-190549]
- segtree: fix get element command with open intervals (Phil Sutter) [RHEL-190549]
- segtree: replace default case by specific types in get_set_intervals() (Phil Sutter) [RHEL-190549]
- src: remove EXPR_SET_ELEM in range_expr_value_{low,high}() (Phil Sutter) [RHEL-190549]
- segtree: rename set_elem_add() to set_elem_expr_add() (Phil Sutter) [RHEL-190549]
- parser_json: fix map/set type confusion crash in map statement parser (Phil Sutter) [RHEL-190549]
- cache: honor -c/--check for reset commands (Phil Sutter) [RHEL-190549]
- tests: py: osf is ip-only (Phil Sutter) [RHEL-190549]
- tests: py: print the file name as intended (Phil Sutter) [RHEL-190549]
- tests: py: don't use a fixed filename (Phil Sutter) [RHEL-190549]
- mnl: Fix ordering of hooks in 'list hooks' output (Phil Sutter) [RHEL-190549]
- segtree: Fix for variable-sized object may not be initialized (Phil Sutter) [RHEL-190549]
- cache: Filter for table when listing flowtables (Phil Sutter) [RHEL-190549]
- cache: Filter for table when listing sets or maps (Phil Sutter) [RHEL-190549]
- cache: Respect family in all list commands (Phil Sutter) [RHEL-190549]
- cache: Include chains, flowtables and objects in netlink debug output (Phil Sutter) [RHEL-190549]
- cache: Relax chain_cache_dump filter application (Phil Sutter) [RHEL-190549]
- parser_bison: add range check for synproxy wscale (Phil Sutter) [RHEL-190549]
- json: complete multi-statement set element support (Phil Sutter) [RHEL-190549]
- segtree: Fix range aggregation on Big Endian (Phil Sutter) [RHEL-190549]
- mergesort: Align concatenation sort order with Big Endian (Phil Sutter) [RHEL-190549]
- mergesort: Fix sorting of string values (Phil Sutter) [RHEL-190549]
- tests: py: any/tcpopt.t.json: Fix JSON equivalent (Phil Sutter) [RHEL-190549]
- expression: expr_build_udata_recurse should recurse (Phil Sutter) [RHEL-190549]
- expression: propagate key datatype for anonymous sets (Phil Sutter) [RHEL-190549]
- netlink_delinearize: also consider exthdr type when trimming binops (Phil Sutter) [RHEL-190549]
- tcpopt: add symbol table for mptcp suboptions (Phil Sutter) [RHEL-190549]
- monitor: fix memleak in setelem cb (Phil Sutter) [RHEL-190549]
- tests: json_echo: Drop rule handle before multi-add (Phil Sutter) [RHEL-190549]
- rule: skip CMD_OBJ_SETELEMS with no elements after set flush (Phil Sutter) [RHEL-190549]
- doc: libnftables-json: Describe RULESET object (Phil Sutter) [RHEL-190549]
- doc: don't suggest to disable GSO (Phil Sutter) [RHEL-190549]
- tests: py: Implement payload_record() (Phil Sutter) [RHEL-190549]
- tests: py: inet/osf.t: Fix element ordering in JSON equivalents (Phil Sutter) [RHEL-190549]
- tests: py: Do not rely upon '[end]' marker (Phil Sutter) [RHEL-190549]
- tests: py: Fix for using wrong payload path (Phil Sutter) [RHEL-190549]
- tests: py: any/ct.t.json.output: Drop leftover entry (Phil Sutter) [RHEL-190549]
- datatype: Fix boolean type on Big Endian (Phil Sutter) [RHEL-190549]
- optimize: Fix verdict expression comparison (Phil Sutter) [RHEL-190549]
- src: parser_json: fix format string bugs (Phil Sutter) [RHEL-190549]
- doc: fix tcpdump example (Phil Sutter) [RHEL-190549]
- tests: py: objects.t: must use input, not output (Phil Sutter) [RHEL-190549]
- fib: Fix for existence check on Big Endian (Phil Sutter) [RHEL-190549]
- tests: Prepare exit codes for automake (Phil Sutter) [RHEL-190549]
- monitor: Inform JSON printer when reporting an object delete event (Phil Sutter) [RHEL-190549]
- monitor: Recognize flowtable add/del events (Phil Sutter) [RHEL-190549]
- tests: monitor: Fix regex collecting expected echo output (Phil Sutter) [RHEL-190549]
- monitor: Quote device names in chain declarations, too (Phil Sutter) [RHEL-190549]
- mnl: continue on ENOBUFS errors when processing batch (Phil Sutter) [RHEL-190549]
- tests: monitor: Fix for flag arrays in JSON output (Phil Sutter) [RHEL-190549]
- mnl: silence compiler warning (Phil Sutter) [RHEL-190549]
- fib: restore JSON output for relational expressions (Phil Sutter) [RHEL-190549]
- src: ensure chain policy evaluation when specified (Phil Sutter) [RHEL-190549]
- segtree: incorrect type when aggregating concatenated set ranges (Phil Sutter) [RHEL-190549]
- json: Do not reduce single-item arrays on output (Phil Sutter) [RHEL-190549]
- tests: py: Fix tests added for 'icmpv6 taddr' support (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entry from ip/snat.t.payload (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entries from ip6/{ct,meta}.t.json (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entry from ip/snat.t.json (Phil Sutter) [RHEL-190549]
- tests: py: Drop duplicate test from inet/vxlan.t (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entry from inet/tcp.t.json (Phil Sutter) [RHEL-190549]
- tests: py: Drop duplicate test from inet/gretap.t (Phil Sutter) [RHEL-190549]
- tests: py: Drop duplicate test from inet/gre.t (Phil Sutter) [RHEL-190549]
- tests: py: Drop duplicate test from inet/geneve.t (Phil Sutter) [RHEL-190549]
- tests: py: Drop stale entries since redundant test case removal (Phil Sutter) [RHEL-190549]
- src: netlink: netlink_delinearize_table() may return NULL (Phil Sutter) [RHEL-190549]
- doc: nft.8: Minor NAT STATEMENTS section review (Phil Sutter) [RHEL-190549]
- mnl: Call mnl_attr_nest_end() just once (Phil Sutter) [RHEL-190549]
- evaluate: validate set expression type before accessing flags (Phil Sutter) [RHEL-190549]
- rule: print chain and flowtable devices in quotes (Phil Sutter) [RHEL-190549]
- tests: py: re-enables nft-test.py to load the local nftables.py (Phil Sutter) [RHEL-190549]
- fib: allow to use it in set statements (Phil Sutter) [RHEL-190549]
- fib: allow to check if route exists in maps (Phil Sutter) [RHEL-190549]
- tests: shell: Fix ifname_based_hooks feature check (Phil Sutter) [RHEL-190549]
- json: reject too long interface names (Phil Sutter) [RHEL-190549]
- tests/py: clean up set backend support fallout (Phil Sutter) [RHEL-190549]
- cache: assert name is non-nul when looking up (Phil Sutter) [RHEL-190549]
- parser_bison: only reset by name is supported by now (Phil Sutter) [RHEL-190549]
- rule: skip fuzzy lookup if object name is not available (Phil Sutter) [RHEL-190549]
- parser_bison: allow delete command with map via handle (Phil Sutter) [RHEL-190549]
- debug: include kernel set information on cache fill (Phil Sutter) [RHEL-190549]
- tests/py: prepare for set debug change (Phil Sutter) [RHEL-190549]
- src: BASECHAIN flag no longer implies presence of priority expression (Phil Sutter) [RHEL-190549]
- netlink: Avoid crash upon missing NFTNL_OBJ_CT_TIMEOUT_ARRAY attribute (Phil Sutter) [RHEL-190549]
- tests: py: Properly fix JSON equivalents for netdev/reject.t (Phil Sutter) [RHEL-190549]
- tests: shell: Adjust to ifname-based hooks (Phil Sutter) [RHEL-190549]
- tests: shell: combine dormant flag with netdevice removal (Phil Sutter) [RHEL-190549]
- tests: monitor: Fix for single flag array avoidance (Phil Sutter) [RHEL-190549]
- netlink: Do not allocate a bogus flowtable priority expr (Phil Sutter) [RHEL-190549]
- netlink: Fix for potential crash parsing a flowtable (Phil Sutter) [RHEL-190549]
- json: work around fuzzer-induced assert crashes (Phil Sutter) [RHEL-190549]
- json: prevent null deref if chain->policy is not set (Phil Sutter) [RHEL-190549]
- tests: py: fix json single-flag output for fib & synproxy (Phil Sutter) [RHEL-190549]
- tests: shell: check for features not available in 5.4 (Phil Sutter) [RHEL-190549]
- netlink: Avoid potential NULL-ptr deref parsing set elem expressions (Phil Sutter) [RHEL-190549]
- netlink: Catch unknown types when deserializing objects (Phil Sutter) [RHEL-190549]
- json: Introduce json_add_array_new() (Phil Sutter) [RHEL-190549]
- json: Fix for memleak in __binop_expr_json (Phil Sutter) [RHEL-190549]
- json: Accept more than two operands in binary expressions (Phil Sutter) [RHEL-190549]
- json: Print single fib flag as non-array (Phil Sutter) [RHEL-190549]
- tests: shell: Add test case for JSON 'flags' arrays (Phil Sutter) [RHEL-190549]
- json: Print single set flag as non-array (Phil Sutter) [RHEL-190549]
- json: Print single synproxy flags as non-array (Phil Sutter) [RHEL-190549]
- parser_json: Introduce parse_flags_array() (Phil Sutter) [RHEL-190549]
- doc: Fix typo in nat statement 'prefix' description (Phil Sutter) [RHEL-190549]
- netlink: bogus concatenated set ranges with netlink message overrun (Phil Sutter) [RHEL-190549]
- parser_bison: add selector_expr rule to restrict typeof_expr (Phil Sutter) [RHEL-190549]
- optimize: invalidate merge in case of duplicated key in set/map (Phil Sutter) [RHEL-190549]
- evaluate: bail out if ct saddr/daddr dependency cannot be inserted (Phil Sutter) [RHEL-190549]
- parser_json: bail out on malformed statement in set (Phil Sutter) [RHEL-190549]
- parser_json: reject empty jump/goto chain (Phil Sutter) [RHEL-190549]
- parser_json: allow statement stateful statement only in set elements (Phil Sutter) [RHEL-190549]
- cache: prevent possible crash rule filter is NULL (Phil Sutter) [RHEL-190549]
- optimize: expand expression list when merging into concatenation (Phil Sutter) [RHEL-190549]
- cache: don't crash when filter is NULL (Phil Sutter) [RHEL-190549]
- evaluate: only allow stateful statements in set and map definitions (Phil Sutter) [RHEL-190549]
- evaluate: compact STMT_F_STATEFUL checks (Phil Sutter) [RHEL-190549]
- json: don't BUG when asked to list synproxies (Phil Sutter) [RHEL-190549]
- optimize: incorrect comparison for reject statement (Phil Sutter) [RHEL-190549]
- optimize: compact bitmask matching in set/map (Phil Sutter) [RHEL-190549]
- tests: shell: missing ct count elements in new set_stmt test (Phil Sutter) [RHEL-190549]
- evaluate: don't update cache for anonymous chains (Phil Sutter) [RHEL-190549]
- json: make sure timeout list is initialised (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate connlimit grammar rule for set elements (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate last grammar rule for set elements (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate quota grammar rule for set elements (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate limit grammar rule for set elements (Phil Sutter) [RHEL-190549]
- parser_bison: consolidate counter grammar rule for set elements (Phil Sutter) [RHEL-190549]
- tests: shell: extend coverage for set element statements (Phil Sutter) [RHEL-190549]
- evaluate: fix assertion failure with malformed map definitions (Phil Sutter) [RHEL-190549]
- evaluate: don't allow nat map with specified protocol (Phil Sutter) [RHEL-190549]
- parser_bison: reject non-serializeable typeof expressions (Phil Sutter) [RHEL-190549]
- netlink: fix stack buffer overrun when emitting ranged expressions (Phil Sutter) [RHEL-190549]
- src: print set element with multi-word description in single one line (Phil Sutter) [RHEL-190549]
- tests: shell: detach synproxy test (Phil Sutter) [RHEL-190549]
- src: do not merge a set with a erroneous one (Phil Sutter) [RHEL-190549]
- segtree: incomplete output in get element command with maps (Phil Sutter) [RHEL-190549]
- evaluate: release existing datatype when evaluating unary expression (Phil Sutter) [RHEL-190549]
- segtree: fix string data initialisation (Phil Sutter) [RHEL-190549]
- payload: honor inner payload description in payload_expr_cmp() (Phil Sutter) [RHEL-190549]
- payload: return early if dependency is not a payload expression (Phil Sutter) [RHEL-190549]
- evaluate: optimize zero length range (Phil Sutter) [RHEL-190549]
- fib: Change data type of fib oifname to "ifname" (Phil Sutter) [RHEL-190549]
- evaluate: auto-merge is only available for singleton interval sets (Phil Sutter) [RHEL-190549]
- parser_bison: compact and simplify list and reset syntax (Phil Sutter) [RHEL-190549]
- parser_bison: turn redundant ip option type field match into boolean (Phil Sutter) [RHEL-190549]
- datatype: clamp boolean value to 0 and 1 (Phil Sutter) [RHEL-190549]
- tests: shell: delete netdev chain after test (Phil Sutter) [RHEL-190549]
- ipopt: use ipv4 address datatype for address field in ip options (Phil Sutter) [RHEL-190549]
- netlink_delinarize: fix bogus munging of mask value (Phil Sutter) [RHEL-190549]
- evaluate: remove variable shadowing (Phil Sutter) [RHEL-190549]
- intervals: do not merge intervals with different timeout (Phil Sutter) [RHEL-190549]
- src: add EXPR_RANGE_VALUE expression and use it (Phil Sutter) [RHEL-190549]
- intervals: add helper function to set previous element (Phil Sutter) [RHEL-190549]
- parser_bison: fix UaF when reporting table parse error (Phil Sutter) [RHEL-190549]
- intervals: set internal element location with the deletion trigger (Phil Sutter) [RHEL-190549]
- optimize: compare expression length (Phil Sutter) [RHEL-190549]
- tests: py: Fix for storing payload into missing file (Phil Sutter) [RHEL-190549]
- json: Support typeof in set and map types (Phil Sutter) [RHEL-190549]
- json: collapse set element commands from parser (Phil Sutter) [RHEL-190549]
- doc: extend description of fib expression (Phil Sutter) [RHEL-190549]
- tests: monitor: fix up test case breakage (Phil Sutter) [RHEL-190549]
- src: fix extended netlink error reporting with large set elements (Phil Sutter) [RHEL-190549]
- mnl: rename to mnl_seqnum_alloc() to mnl_seqnum_inc() (Phil Sutter) [RHEL-190549]
- mnl: update cmd_add_loc() to take struct nlmsghdr (Phil Sutter) [RHEL-190549]
- rule: netlink attribute offset is uint32_t for struct nlerr_loc (Phil Sutter) [RHEL-190549]
- src: collapse set element commands from parser (Phil Sutter) [RHEL-190549]
- libnftables-json: fix raw payload expression documentation (Phil Sutter) [RHEL-190549]
- cache: initialize filter when fetching implicit chains (Phil Sutter) [RHEL-190549]
- tests: py: fix up udp csum fixup output (Phil Sutter) [RHEL-190549]
- proto: use NFT_PAYLOAD_L4CSUM_PSEUDOHDR flag to mangle UDP checksum (Phil Sutter) [RHEL-190549]
- tests: shell: stabilize packetpath/payload (Phil Sutter) [RHEL-190549]
- libnftables: Zero ctx->vars after freeing it (Phil Sutter) [RHEL-190549]
- cache: position does not require full cache (Phil Sutter) [RHEL-190549]
- cache: relax requirement for replace rule command (Phil Sutter) [RHEL-190549]
- cache: remove full cache requirement when echo flag is set on (Phil Sutter) [RHEL-190549]
- cache: assert filter when calling nft_cache_evaluate() (Phil Sutter) [RHEL-190549]
- cache: consolidate reset command (Phil Sutter) [RHEL-190549]
- cache: add filtering support for objects (Phil Sutter) [RHEL-190549]
- cache: only dump rules for the given table (Phil Sutter) [RHEL-190549]
- cache: accumulate flags in batch (Phil Sutter) [RHEL-190549]
- cache: reset filter for each command (Phil Sutter) [RHEL-190549]
- parser_json: fix several expression memleaks from error path (Phil Sutter) [RHEL-190549]
- parser_json: release buffer returned by json_dumps (Phil Sutter) [RHEL-190549]
- json: Support maps with concatenated data (Phil Sutter) [RHEL-190549]
- parser_json: fix crash in json_parse_set_stmt_list (Phil Sutter) [RHEL-190549]
- parser_bison: allow 0 burst in limit rate byte mode (Phil Sutter) [RHEL-190549]
- datatype: improve error reporting when time unit is not correct (Phil Sutter) [RHEL-190549]
- cache: rule by index requires full cache (Phil Sutter) [RHEL-190549]
- datatype: reject rate in quota statement (Phil Sutter) [RHEL-190549]
- optimize: skip variables in nat statements (Phil Sutter) [RHEL-190549]
- parser_json: use stdin buffer if available (Phil Sutter) [RHEL-190549]
- libnftables: skip useable checks for /dev/stdin (Phil Sutter) [RHEL-190549]
- optimize: clone counter before insertion into set element (Phil Sutter) [RHEL-190549]
- segtree: set on EXPR_F_KERNEL flag for catchall elements in the cache (Phil Sutter) [RHEL-190549]
- evaluate: set on expr->len for catchall set elements (Phil Sutter) [RHEL-190549]
- parser_bison: recursive table declaration in deprecated meter statement (Phil Sutter) [RHEL-190549]
- intervals: fix element deletions with maps (Phil Sutter) [RHEL-190549]
- src: add string preprocessor and use it for log prefix string (Phil Sutter) [RHEL-190549]
- tests: shell: skip ip option tests if kernel does not support it (Phil Sutter) [RHEL-190549]
- cmd: skip variable set elements when collapsing commands (Phil Sutter) [RHEL-190549]
- cmd: provide better hint if chain is already declared with different type/hook/priority (Phil Sutter) [RHEL-190549]
- monitor: too large shift exponent displaying payload expression (Phil Sutter) [RHEL-190549]
- scanner: inet_pton() allows for broader IPv4-Mapped IPv6 addresses (Phil Sutter) [RHEL-190549]
- evaluate: Fix incorrect checking the `base` variable in case of IPV6 (Phil Sutter) [RHEL-190549]
- evaluate: bogus protocol conflicts in vlan with implicit dependencies (Phil Sutter) [RHEL-190549]
- cache: check for NFT_CACHE_REFRESH in current requested cache too (Phil Sutter) [RHEL-190549]
- doc: nft.8: Fix markup in ct expectation synopsis (Phil Sutter) [RHEL-190549]
- mergesort: Avoid accidental set element reordering (Phil Sutter) [RHEL-190549]
- doc: nft.8: Two minor synopsis fixups (Phil Sutter) [RHEL-190549]
- tests: shell: check for reset tcp options support (Phil Sutter) [RHEL-190549]
- tests: shell: payload matching requires egress support (Phil Sutter) [RHEL-190549]
- tests: py: complete icmp and icmpv6 update (Phil Sutter) [RHEL-190549]
- src: disentangle ICMP code types (Phil Sutter) [RHEL-190549]
- evaluate: display "Range negative size" error (Phil Sutter) [RHEL-190549]
- netlink_delinearize: restore binop syntax when listing ruleset for flags (Phil Sutter) [RHEL-190549]
- doc: libnftables-json: Drop invalid ops from match expression (Phil Sutter) [RHEL-190549]
- parser: json: Support for synproxy objects (Phil Sutter) [RHEL-190549]
- tests: py: add payload merging test cases (Phil Sutter) [RHEL-190549]
- nftables: do mot merge payloads on negation (Phil Sutter) [RHEL-190549]
- rule: fix ASAN errors in chain priority to textual names (Phil Sutter) [RHEL-190549]
- parser: compact type/typeof set rules (Phil Sutter) [RHEL-190549]
- parser: compact interval typeof rules (Phil Sutter) [RHEL-190549]
- src: improve error reporting for destroy command (Phil Sutter) [RHEL-190549]
- tests: shell: permit use of host-endian constant values in set lookup keys (Phil Sutter) [RHEL-190549]
- evaluate: permit use of host-endian constant values in set lookup keys (Phil Sutter) [RHEL-190549]
- expression: missing line in describe command with invalid expression (Phil Sutter) [RHEL-190549]
- netlink_delinearize: move concat and value postprocessing to helpers (Phil Sutter) [RHEL-190549]
- evaluate: skip byteorder conversion for selector smaller than 2 bytes (Phil Sutter) [RHEL-190549]
- cache: Optimize caching for 'list tables' command (Phil Sutter) [RHEL-190549]
- evaluate: fix check for unknown in cmd_op_to_name (Phil Sutter) [RHEL-190549]
- evaluate: don't assert on net/transport header conflict (Phil Sutter) [RHEL-190549]
- json: Support sets' auto-merge option (Phil Sutter) [RHEL-190549]
- rule: fix sym refcount assertion (Phil Sutter) [RHEL-190549]
- evaluate: error out when store needs more than one 128bit register of align fixup (Phil Sutter) [RHEL-190549]
- evaluate: do not fetch next expression on runaway number of concatenation components (Phil Sutter) [RHEL-190549]
- evaluate: skip anonymous set optimization for concatenations (Phil Sutter) [RHEL-190549]
- evaluate: add missing range checks for dup,fwd and payload statements (Phil Sutter) [RHEL-190549]
- doc: incorrect datatype description for icmpv6_type and icmpvx_code (Phil Sutter) [RHEL-190549]
- tests: shell: prefer project nft to system-wide nft (Phil Sutter) [RHEL-190549]
- parser_bison: ensure all timeout policy names are released (Phil Sutter) [RHEL-190549]
- netlink: fix stack overflow due to erroneous rounding (Phil Sutter) [RHEL-190549]
- parser_bison: error out on duplicated type/typeof/element keywords (Phil Sutter) [RHEL-190549]
- tests: shell: add test to cover payload transport match and mangle (Phil Sutter) [RHEL-190549]
- evaluate: fix stack overflow with huge priority string (Phil Sutter) [RHEL-190549]
- src: reject large raw payload and concat expressions (Phil Sutter) [RHEL-190549]
- evaluate: exthdr: statement arg must be not be a range (Phil Sutter) [RHEL-190549]
- meta: fix tc classid parsing out-of-bounds access (Phil Sutter) [RHEL-190549]
- parser_bison: close chain scope before chain release (Phil Sutter) [RHEL-190549]
- evaluate: fix bogus assertion failure with boolean datatype (Phil Sutter) [RHEL-190549]
- parser_bison: fix objref statement corruption (Phil Sutter) [RHEL-190549]
- tests: py: missing json output in meta.t with vlan mapping (Phil Sutter) [RHEL-190549]
- evaluate: reset statement length context before evaluating statement (Phil Sutter) [RHEL-190549]
- parser: tcpopt: fix tcp option parsing with NUM + length field (Phil Sutter) [RHEL-190549]
- evaluate: reject set definition with no key (Phil Sutter) [RHEL-190549]
- monitor: add support for concatenated set ranges (Phil Sutter) [RHEL-190549]
- evaluate: disable meta set with ranges (Phil Sutter) [RHEL-190549]
- evaluate: prevent assert when evaluating very large shift values (Phil Sutter) [RHEL-190549]
- evaluate: reject sets with no key (Phil Sutter) [RHEL-190549]
- evaluate: clone unary expression datatype to deal with dynamic datatype (Phil Sutter) [RHEL-190549]
- tests: shell: split nat inet tests (Phil Sutter) [RHEL-190549]
- evaluate: bogus error when adding devices to flowtable (Phil Sutter) [RHEL-190549]
- tests: shell: flush connlimit sets (Phil Sutter) [RHEL-190549]
- tests: shell: adjust add-after-delete flowtable for older kernels (Phil Sutter) [RHEL-190549]
- evaluate: fix rule replacement with anon sets (Phil Sutter) [RHEL-190549]
- tests: shell: skip if kernel does not support flowtable counter (Phil Sutter) [RHEL-190549]
- tests: shell: restore pipapo and chain binding coverage in standalone 30s-stress (Phil Sutter) [RHEL-190549]
- json: fix use after free in table_flags_json() (Phil Sutter) [RHEL-190549]
- src: expand create commands (Phil Sutter) [RHEL-190549]
- tests: shell: split set NAT interval test (Phil Sutter) [RHEL-190549]
- tests: shell: split merge nat optimization in two tests (Phil Sutter) [RHEL-190549]
- netlink: fix buffer size for user data in netlink_delinearize_chain() (Phil Sutter) [RHEL-190549]
- src: remove xfree() and use plain free() (Phil Sutter) [RHEL-190549]
- src: add free_const() and use it instead of xfree() (Phil Sutter) [RHEL-190549]
- evaluate: place byteorder conversion before rshift in payload expressions (Phil Sutter) [RHEL-190549]
- evaluate: reset statement length context only for set mappings (Phil Sutter) [RHEL-190549]
- meta: fix hour decoding when timezone offset is negative (Phil Sutter) [RHEL-190549]
- tproxy: Drop artificial port printing restriction (Phil Sutter) [RHEL-190549]
- tests/shell: fix mount command in "test-wrapper.sh" (Phil Sutter) [RHEL-190549]
- parser_bison: fix length check for ifname in ifname_expr_alloc() (Phil Sutter) [RHEL-190549]
- tests/shell: cover long interface name in "0042chain_variable_0" test (Phil Sutter) [RHEL-190549]
- tests/shell: add missing "elem_opts_compat_0.nodump" file (Phil Sutter) [RHEL-190549]
- parser_bison: Fix for broken compatibility with older dumps (Phil Sutter) [RHEL-190549]
Resolves: RHEL-190549
770 lines
21 KiB
Diff
770 lines
21 KiB
Diff
From f3cf701e78370d70683f7421a9e42b2da1f0a84d Mon Sep 17 00:00:00 2001
|
|
From: Phil Sutter <psutter@redhat.com>
|
|
Date: Fri, 17 Jul 2026 11:13:20 +0200
|
|
Subject: [PATCH] parser_json: Introduce parse_flags_array()
|
|
|
|
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
|
Upstream Status: nftables commit 3550dd69632f3a883ab6593daeffb514c67dfb8c
|
|
|
|
commit 3550dd69632f3a883ab6593daeffb514c67dfb8c
|
|
Author: Phil Sutter <phil@nwl.cc>
|
|
Date: Thu Apr 10 16:42:42 2025 +0200
|
|
|
|
parser_json: Introduce parse_flags_array()
|
|
|
|
Various objects support a 'flags' property with value usually being an
|
|
array of strings. There is a special case, when merely a single flag is
|
|
set: The value may be a string representing this flag.
|
|
|
|
Introduce a function assisting in parsing this polymorphic value. Have
|
|
callers pass a parser callback translating a single flag name into a
|
|
corresponding value. Luckily, these single flag parsers are very common
|
|
already.
|
|
|
|
As a side-effect, enable the single flag spec for set flags as well and
|
|
update the documentation accordingly.
|
|
|
|
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
|
|
|
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
|
---
|
|
doc/libnftables-json.adoc | 5 +-
|
|
src/parser_json.c | 466 +++++++++++---------------------------
|
|
2 files changed, 136 insertions(+), 335 deletions(-)
|
|
|
|
diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
|
|
index b90a1fc..ab4223d 100644
|
|
--- a/doc/libnftables-json.adoc
|
|
+++ b/doc/libnftables-json.adoc
|
|
@@ -317,7 +317,7 @@ ____
|
|
"handle":* 'NUMBER'*,
|
|
"type":* 'SET_TYPE'*,
|
|
"policy":* 'SET_POLICY'*,
|
|
- "flags": [* 'SET_FLAG_LIST' *],
|
|
+ "flags":* 'SET_FLAGS'*,
|
|
"elem":* 'SET_ELEMENTS'*,
|
|
"timeout":* 'NUMBER'*,
|
|
"gc-interval":* 'NUMBER'*,
|
|
@@ -333,7 +333,7 @@ ____
|
|
"type":* 'SET_TYPE'*,
|
|
"map":* 'STRING'*,
|
|
"policy":* 'SET_POLICY'*,
|
|
- "flags": [* 'SET_FLAG_LIST' *],
|
|
+ "flags":* 'SET_FLAGS'*,
|
|
"elem":* 'SET_ELEMENTS'*,
|
|
"timeout":* 'NUMBER'*,
|
|
"gc-interval":* 'NUMBER'*,
|
|
@@ -344,6 +344,7 @@ ____
|
|
'SET_TYPE' := 'STRING' | *[* 'SET_TYPE_LIST' *]* | *{ "typeof":* 'EXPRESSION' *}*
|
|
'SET_TYPE_LIST' := 'STRING' [*,* 'SET_TYPE_LIST' ]
|
|
'SET_POLICY' := *"performance"* | *"memory"*
|
|
+'SET_FLAGS' := 'SET_FLAG' | *[* 'SET_FLAG_LIST' *]*
|
|
'SET_FLAG_LIST' := 'SET_FLAG' [*,* 'SET_FLAG_LIST' ]
|
|
'SET_FLAG' := *"constant"* | *"interval"* | *"timeout"*
|
|
'SET_ELEMENTS' := 'EXPRESSION' | *[* 'EXPRESSION_LIST' *]*
|
|
diff --git a/src/parser_json.c b/src/parser_json.c
|
|
index ca33c6c..dc038f5 100644
|
|
--- a/src/parser_json.c
|
|
+++ b/src/parser_json.c
|
|
@@ -198,6 +198,60 @@ static int json_unpack_stmt(struct json_ctx *ctx, json_t *root,
|
|
return 1;
|
|
}
|
|
|
|
+/**
|
|
+ * parse_flags_array - parse JSON property as an array of flags
|
|
+ *
|
|
+ * @ctx: JSON parser context
|
|
+ * @obj: JSON object to extract property from
|
|
+ * @key: name of property containing the flags array
|
|
+ * @flag_parser: Callback parsing a single flag, returns 0 on error
|
|
+ *
|
|
+ * The property value may be a string representing a single flag or an array of
|
|
+ * strings representing a number of flags whose values are ORed together.
|
|
+ *
|
|
+ * @return: Combined flag value, 0 if no such property found or -1 if data is
|
|
+ * malformed or flag parsing failed.
|
|
+ */
|
|
+static int parse_flags_array(struct json_ctx *ctx, json_t *obj, const char *key,
|
|
+ unsigned int (*flag_parser)(const char *flag))
|
|
+{
|
|
+ json_t *value = json_object_get(obj, key), *tmp;
|
|
+ size_t index;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (!value)
|
|
+ return 0;
|
|
+
|
|
+ if (json_is_string(value)) {
|
|
+ ret = flag_parser(json_string_value(value));
|
|
+ return ret ?: -1;
|
|
+ }
|
|
+
|
|
+ if (!json_is_array(value)) {
|
|
+ json_error(ctx,
|
|
+ "Expecting string or array in '%s' property.", key);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ json_array_foreach(value, index, tmp) {
|
|
+ int flag = 0;
|
|
+
|
|
+ if (json_is_string(tmp))
|
|
+ flag = flag_parser(json_string_value(tmp));
|
|
+
|
|
+ if (!flag) {
|
|
+ json_error(ctx,
|
|
+ "Invalid flag in '%s' property array at index %zu.",
|
|
+ key, index);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ret |= flag;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int parse_family(const char *name, uint32_t *family)
|
|
{
|
|
unsigned int i;
|
|
@@ -1065,7 +1119,7 @@ static struct expr *json_parse_hash_expr(struct json_ctx *ctx,
|
|
return hash_expr;
|
|
}
|
|
|
|
-static int fib_flag_parse(const char *name, int *flags)
|
|
+static unsigned int fib_flag_parse(const char *name)
|
|
{
|
|
const char *fib_flags[] = {
|
|
"saddr",
|
|
@@ -1077,12 +1131,10 @@ static int fib_flag_parse(const char *name, int *flags)
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < array_size(fib_flags); i++) {
|
|
- if (!strcmp(name, fib_flags[i])) {
|
|
- *flags |= (1 << i);
|
|
- return 0;
|
|
- }
|
|
+ if (!strcmp(name, fib_flags[i]))
|
|
+ return 1 << i;
|
|
}
|
|
- return 1;
|
|
+ return 0;
|
|
}
|
|
|
|
static struct expr *json_parse_fib_expr(struct json_ctx *ctx,
|
|
@@ -1095,11 +1147,9 @@ static struct expr *json_parse_fib_expr(struct json_ctx *ctx,
|
|
[NFT_FIB_RESULT_ADDRTYPE] = "type",
|
|
};
|
|
enum nft_fib_result resultval = NFT_FIB_RESULT_UNSPEC;
|
|
- json_t *flags, *value;
|
|
const char *result;
|
|
- unsigned int i;
|
|
- size_t index;
|
|
int flagval = 0;
|
|
+ unsigned int i;
|
|
|
|
if (json_unpack_err(ctx, root, "{s:s}", "result", &result))
|
|
return NULL;
|
|
@@ -1115,34 +1165,9 @@ static struct expr *json_parse_fib_expr(struct json_ctx *ctx,
|
|
return NULL;
|
|
}
|
|
|
|
- if (!json_unpack(root, "{s:o}", "flags", &flags)) {
|
|
- const char *flag;
|
|
-
|
|
- if (json_is_string(flags)) {
|
|
- flag = json_string_value(flags);
|
|
-
|
|
- if (fib_flag_parse(flag, &flagval)) {
|
|
- json_error(ctx, "Invalid fib flag '%s'.", flag);
|
|
- return NULL;
|
|
- }
|
|
- } else if (!json_is_array(flags)) {
|
|
- json_error(ctx, "Unexpected object type in fib tuple.");
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- json_array_foreach(flags, index, value) {
|
|
- if (!json_is_string(value)) {
|
|
- json_error(ctx, "Unexpected object type in fib flags array at index %zd.", index);
|
|
- return NULL;
|
|
- }
|
|
- flag = json_string_value(value);
|
|
-
|
|
- if (fib_flag_parse(flag, &flagval)) {
|
|
- json_error(ctx, "Invalid fib flag '%s'.", flag);
|
|
- return NULL;
|
|
- }
|
|
- }
|
|
- }
|
|
+ flagval = parse_flags_array(ctx, root, "flags", fib_flag_parse);
|
|
+ if (flagval < 0)
|
|
+ return NULL;
|
|
|
|
/* sanity checks from fib_expr in parser_bison.y */
|
|
|
|
@@ -2102,8 +2127,7 @@ static struct stmt *json_parse_secmark_stmt(struct json_ctx *ctx,
|
|
return stmt;
|
|
}
|
|
|
|
-static int json_parse_nat_flag(struct json_ctx *ctx,
|
|
- json_t *root, int *flags)
|
|
+static unsigned int json_parse_nat_flag(const char *flag)
|
|
{
|
|
const struct {
|
|
const char *flag;
|
|
@@ -2114,51 +2138,16 @@ static int json_parse_nat_flag(struct json_ctx *ctx,
|
|
{ "persistent", NF_NAT_RANGE_PERSISTENT },
|
|
{ "netmap", NF_NAT_RANGE_NETMAP },
|
|
};
|
|
- const char *flag;
|
|
unsigned int i;
|
|
|
|
- assert(flags);
|
|
-
|
|
- if (!json_is_string(root)) {
|
|
- json_error(ctx, "Invalid nat flag type %s, expected string.",
|
|
- json_typename(root));
|
|
- return 1;
|
|
- }
|
|
- flag = json_string_value(root);
|
|
for (i = 0; i < array_size(flag_tbl); i++) {
|
|
- if (!strcmp(flag, flag_tbl[i].flag)) {
|
|
- *flags |= flag_tbl[i].val;
|
|
- return 0;
|
|
- }
|
|
- }
|
|
- json_error(ctx, "Unknown nat flag '%s'.", flag);
|
|
- return 1;
|
|
-}
|
|
-
|
|
-static int json_parse_nat_flags(struct json_ctx *ctx, json_t *root)
|
|
-{
|
|
- int flags = 0;
|
|
- json_t *value;
|
|
- size_t index;
|
|
-
|
|
- if (json_is_string(root)) {
|
|
- json_parse_nat_flag(ctx, root, &flags);
|
|
- return flags;
|
|
- } else if (!json_is_array(root)) {
|
|
- json_error(ctx, "Invalid nat flags type %s.",
|
|
- json_typename(root));
|
|
- return -1;
|
|
- }
|
|
- json_array_foreach(root, index, value) {
|
|
- if (json_parse_nat_flag(ctx, value, &flags))
|
|
- json_error(ctx, "Parsing nat flag at index %zu failed.",
|
|
- index);
|
|
+ if (!strcmp(flag, flag_tbl[i].flag))
|
|
+ return flag_tbl[i].val;
|
|
}
|
|
- return flags;
|
|
+ return 0;
|
|
}
|
|
|
|
-static int json_parse_nat_type_flag(struct json_ctx *ctx,
|
|
- json_t *root, int *flags)
|
|
+static unsigned int json_parse_nat_type_flag(const char *flag)
|
|
{
|
|
const struct {
|
|
const char *flag;
|
|
@@ -2168,47 +2157,13 @@ static int json_parse_nat_type_flag(struct json_ctx *ctx,
|
|
{ "prefix", STMT_NAT_F_PREFIX },
|
|
{ "concat", STMT_NAT_F_CONCAT },
|
|
};
|
|
- const char *flag;
|
|
unsigned int i;
|
|
|
|
- assert(flags);
|
|
-
|
|
- if (!json_is_string(root)) {
|
|
- json_error(ctx, "Invalid nat type flag type %s, expected string.",
|
|
- json_typename(root));
|
|
- return 1;
|
|
- }
|
|
- flag = json_string_value(root);
|
|
for (i = 0; i < array_size(flag_tbl); i++) {
|
|
- if (!strcmp(flag, flag_tbl[i].flag)) {
|
|
- *flags |= flag_tbl[i].val;
|
|
- return 0;
|
|
- }
|
|
- }
|
|
- json_error(ctx, "Unknown nat type flag '%s'.", flag);
|
|
- return 1;
|
|
-}
|
|
-
|
|
-static int json_parse_nat_type_flags(struct json_ctx *ctx, json_t *root)
|
|
-{
|
|
- int flags = 0;
|
|
- json_t *value;
|
|
- size_t index;
|
|
-
|
|
- if (json_is_string(root)) {
|
|
- json_parse_nat_type_flag(ctx, root, &flags);
|
|
- return flags;
|
|
- } else if (!json_is_array(root)) {
|
|
- json_error(ctx, "Invalid nat flags type %s.",
|
|
- json_typename(root));
|
|
- return -1;
|
|
- }
|
|
- json_array_foreach(root, index, value) {
|
|
- if (json_parse_nat_type_flag(ctx, value, &flags))
|
|
- json_error(ctx, "Parsing nat type flag at index %zu failed.",
|
|
- index);
|
|
+ if (!strcmp(flag, flag_tbl[i].flag))
|
|
+ return flag_tbl[i].val;
|
|
}
|
|
- return flags;
|
|
+ return 0;
|
|
}
|
|
|
|
static int nat_type_parse(const char *type)
|
|
@@ -2231,7 +2186,7 @@ static int nat_type_parse(const char *type)
|
|
static struct stmt *json_parse_nat_stmt(struct json_ctx *ctx,
|
|
const char *key, json_t *value)
|
|
{
|
|
- int type, familyval;
|
|
+ int type, familyval, flags;
|
|
struct stmt *stmt;
|
|
json_t *tmp;
|
|
|
|
@@ -2264,24 +2219,20 @@ static struct stmt *json_parse_nat_stmt(struct json_ctx *ctx,
|
|
return NULL;
|
|
}
|
|
}
|
|
- if (!json_unpack(value, "{s:o}", "flags", &tmp)) {
|
|
- int flags = json_parse_nat_flags(ctx, tmp);
|
|
-
|
|
- if (flags < 0) {
|
|
- stmt_free(stmt);
|
|
- return NULL;
|
|
- }
|
|
- stmt->nat.flags = flags;
|
|
+ flags = parse_flags_array(ctx, value, "flags", json_parse_nat_flag);
|
|
+ if (flags < 0) {
|
|
+ stmt_free(stmt);
|
|
+ return NULL;
|
|
}
|
|
- if (!json_unpack(value, "{s:o}", "type_flags", &tmp)) {
|
|
- int flags = json_parse_nat_type_flags(ctx, tmp);
|
|
+ stmt->nat.flags = flags;
|
|
|
|
- if (flags < 0) {
|
|
- stmt_free(stmt);
|
|
- return NULL;
|
|
- }
|
|
- stmt->nat.type_flags = flags;
|
|
+ flags = parse_flags_array(ctx, value, "type_flags",
|
|
+ json_parse_nat_type_flag);
|
|
+ if (flags < 0) {
|
|
+ stmt_free(stmt);
|
|
+ return NULL;
|
|
}
|
|
+ stmt->nat.type_flags = flags;
|
|
|
|
return stmt;
|
|
}
|
|
@@ -2514,8 +2465,7 @@ static struct stmt *json_parse_map_stmt(struct json_ctx *ctx,
|
|
return stmt;
|
|
}
|
|
|
|
-static int json_parse_log_flag(struct json_ctx *ctx,
|
|
- json_t *root, int *flags)
|
|
+static unsigned int json_parse_log_flag(const char *flag)
|
|
{
|
|
const struct {
|
|
const char *flag;
|
|
@@ -2528,47 +2478,13 @@ static int json_parse_log_flag(struct json_ctx *ctx,
|
|
{ "ether", NF_LOG_MACDECODE },
|
|
{ "all", NF_LOG_MASK },
|
|
};
|
|
- const char *flag;
|
|
unsigned int i;
|
|
|
|
- assert(flags);
|
|
-
|
|
- if (!json_is_string(root)) {
|
|
- json_error(ctx, "Invalid log flag type %s, expected string.",
|
|
- json_typename(root));
|
|
- return 1;
|
|
- }
|
|
- flag = json_string_value(root);
|
|
for (i = 0; i < array_size(flag_tbl); i++) {
|
|
- if (!strcmp(flag, flag_tbl[i].flag)) {
|
|
- *flags |= flag_tbl[i].val;
|
|
- return 0;
|
|
- }
|
|
- }
|
|
- json_error(ctx, "Unknown log flag '%s'.", flag);
|
|
- return 1;
|
|
-}
|
|
-
|
|
-static int json_parse_log_flags(struct json_ctx *ctx, json_t *root)
|
|
-{
|
|
- int flags = 0;
|
|
- json_t *value;
|
|
- size_t index;
|
|
-
|
|
- if (json_is_string(root)) {
|
|
- json_parse_log_flag(ctx, root, &flags);
|
|
- return flags;
|
|
- } else if (!json_is_array(root)) {
|
|
- json_error(ctx, "Invalid log flags type %s.",
|
|
- json_typename(root));
|
|
- return -1;
|
|
- }
|
|
- json_array_foreach(root, index, value) {
|
|
- if (json_parse_log_flag(ctx, value, &flags))
|
|
- json_error(ctx, "Parsing log flag at index %zu failed.",
|
|
- index);
|
|
+ if (!strcmp(flag, flag_tbl[i].flag))
|
|
+ return flag_tbl[i].val;
|
|
}
|
|
- return flags;
|
|
+ return 0;
|
|
}
|
|
|
|
static struct stmt *json_parse_log_stmt(struct json_ctx *ctx,
|
|
@@ -2576,8 +2492,7 @@ static struct stmt *json_parse_log_stmt(struct json_ctx *ctx,
|
|
{
|
|
const char *tmpstr;
|
|
struct stmt *stmt;
|
|
- json_t *jflags;
|
|
- int tmp;
|
|
+ int tmp, flags;
|
|
|
|
stmt = log_stmt_alloc(int_loc);
|
|
|
|
@@ -2608,20 +2523,17 @@ static struct stmt *json_parse_log_stmt(struct json_ctx *ctx,
|
|
stmt->log.level = level;
|
|
stmt->log.flags |= STMT_LOG_LEVEL;
|
|
}
|
|
- if (!json_unpack(value, "{s:o}", "flags", &jflags)) {
|
|
- int flags = json_parse_log_flags(ctx, jflags);
|
|
-
|
|
- if (flags < 0) {
|
|
- stmt_free(stmt);
|
|
- return NULL;
|
|
- }
|
|
- stmt->log.logflags = flags;
|
|
+ flags = parse_flags_array(ctx, value, "flags", json_parse_log_flag);
|
|
+ if (flags < 0) {
|
|
+ stmt_free(stmt);
|
|
+ return NULL;
|
|
}
|
|
+ stmt->log.logflags = flags;
|
|
+
|
|
return stmt;
|
|
}
|
|
|
|
-static int json_parse_synproxy_flag(struct json_ctx *ctx,
|
|
- json_t *root, int *flags)
|
|
+static unsigned int json_parse_synproxy_flag(const char *flag)
|
|
{
|
|
const struct {
|
|
const char *flag;
|
|
@@ -2630,54 +2542,19 @@ static int json_parse_synproxy_flag(struct json_ctx *ctx,
|
|
{ "timestamp", NF_SYNPROXY_OPT_TIMESTAMP },
|
|
{ "sack-perm", NF_SYNPROXY_OPT_SACK_PERM },
|
|
};
|
|
- const char *flag;
|
|
unsigned int i;
|
|
|
|
- assert(flags);
|
|
-
|
|
- if (!json_is_string(root)) {
|
|
- json_error(ctx, "Invalid synproxy flag type %s, expected string.",
|
|
- json_typename(root));
|
|
- return 1;
|
|
- }
|
|
- flag = json_string_value(root);
|
|
for (i = 0; i < array_size(flag_tbl); i++) {
|
|
- if (!strcmp(flag, flag_tbl[i].flag)) {
|
|
- *flags |= flag_tbl[i].val;
|
|
- return 0;
|
|
- }
|
|
- }
|
|
- json_error(ctx, "Unknown synproxy flag '%s'.", flag);
|
|
- return 1;
|
|
-}
|
|
-
|
|
-static int json_parse_synproxy_flags(struct json_ctx *ctx, json_t *root)
|
|
-{
|
|
- int flags = 0;
|
|
- json_t *value;
|
|
- size_t index;
|
|
-
|
|
- if (json_is_string(root)) {
|
|
- json_parse_synproxy_flag(ctx, root, &flags);
|
|
- return flags;
|
|
- } else if (!json_is_array(root)) {
|
|
- json_error(ctx, "Invalid synproxy flags type %s.",
|
|
- json_typename(root));
|
|
- return -1;
|
|
- }
|
|
- json_array_foreach(root, index, value) {
|
|
- if (json_parse_synproxy_flag(ctx, value, &flags))
|
|
- json_error(ctx, "Parsing synproxy flag at index %zu failed.",
|
|
- index);
|
|
+ if (!strcmp(flag, flag_tbl[i].flag))
|
|
+ return flag_tbl[i].val;
|
|
}
|
|
- return flags;
|
|
+ return 0;
|
|
}
|
|
|
|
static struct stmt *json_parse_synproxy_stmt(struct json_ctx *ctx,
|
|
const char *key, json_t *value)
|
|
{
|
|
struct stmt *stmt = NULL;
|
|
- json_t *jflags;
|
|
int tmp, flags;
|
|
|
|
if (json_typeof(value) == JSON_NULL) {
|
|
@@ -2707,15 +2584,16 @@ static struct stmt *json_parse_synproxy_stmt(struct json_ctx *ctx,
|
|
stmt->synproxy.wscale = tmp;
|
|
stmt->synproxy.flags |= NF_SYNPROXY_OPT_WSCALE;
|
|
}
|
|
- if (!json_unpack(value, "{s:o}", "flags", &jflags)) {
|
|
+
|
|
+ flags = parse_flags_array(ctx, value, "flags",
|
|
+ json_parse_synproxy_flag);
|
|
+ if (flags < 0) {
|
|
+ stmt_free(stmt);
|
|
+ return NULL;
|
|
+ }
|
|
+ if (flags) {
|
|
if (!stmt)
|
|
stmt = synproxy_stmt_alloc(int_loc);
|
|
- flags = json_parse_synproxy_flags(ctx, jflags);
|
|
-
|
|
- if (flags < 0) {
|
|
- stmt_free(stmt);
|
|
- return NULL;
|
|
- }
|
|
stmt->synproxy.flags |= flags;
|
|
}
|
|
|
|
@@ -2810,14 +2688,12 @@ static struct stmt *json_parse_meter_stmt(struct json_ctx *ctx,
|
|
return stmt;
|
|
}
|
|
|
|
-static int queue_flag_parse(const char *name, uint16_t *flags)
|
|
+static unsigned int queue_flag_parse(const char *name)
|
|
{
|
|
if (!strcmp(name, "bypass"))
|
|
- *flags |= NFT_QUEUE_FLAG_BYPASS;
|
|
+ return NFT_QUEUE_FLAG_BYPASS;
|
|
else if (!strcmp(name, "fanout"))
|
|
- *flags |= NFT_QUEUE_FLAG_CPU_FANOUT;
|
|
- else
|
|
- return 1;
|
|
+ return NFT_QUEUE_FLAG_CPU_FANOUT;
|
|
return 0;
|
|
}
|
|
|
|
@@ -2825,8 +2701,8 @@ static struct stmt *json_parse_queue_stmt(struct json_ctx *ctx,
|
|
const char *key, json_t *value)
|
|
{
|
|
struct expr *qexpr = NULL;
|
|
- uint16_t flags = 0;
|
|
json_t *tmp;
|
|
+ int flags;
|
|
|
|
if (!json_unpack(value, "{s:o}", "num", &tmp)) {
|
|
qexpr = json_parse_stmt_expr(ctx, tmp);
|
|
@@ -2835,43 +2711,13 @@ static struct stmt *json_parse_queue_stmt(struct json_ctx *ctx,
|
|
return NULL;
|
|
}
|
|
}
|
|
- if (!json_unpack(value, "{s:o}", "flags", &tmp)) {
|
|
- const char *flag;
|
|
- size_t index;
|
|
- json_t *val;
|
|
-
|
|
- if (json_is_string(tmp)) {
|
|
- flag = json_string_value(tmp);
|
|
-
|
|
- if (queue_flag_parse(flag, &flags)) {
|
|
- json_error(ctx, "Invalid queue flag '%s'.",
|
|
- flag);
|
|
- expr_free(qexpr);
|
|
- return NULL;
|
|
- }
|
|
- } else if (!json_is_array(tmp)) {
|
|
- json_error(ctx, "Unexpected object type in queue flags.");
|
|
- expr_free(qexpr);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- json_array_foreach(tmp, index, val) {
|
|
- if (!json_is_string(val)) {
|
|
- json_error(ctx, "Invalid object in queue flag array at index %zu.",
|
|
- index);
|
|
- expr_free(qexpr);
|
|
- return NULL;
|
|
- }
|
|
- flag = json_string_value(val);
|
|
|
|
- if (queue_flag_parse(flag, &flags)) {
|
|
- json_error(ctx, "Invalid queue flag '%s'.",
|
|
- flag);
|
|
- expr_free(qexpr);
|
|
- return NULL;
|
|
- }
|
|
- }
|
|
+ flags = parse_flags_array(ctx, value, "flags", queue_flag_parse);
|
|
+ if (flags < 0) {
|
|
+ expr_free(qexpr);
|
|
+ return NULL;
|
|
}
|
|
+
|
|
return queue_stmt_alloc(int_loc, qexpr, flags);
|
|
}
|
|
|
|
@@ -2982,45 +2828,6 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root)
|
|
return NULL;
|
|
}
|
|
|
|
-static int json_parse_table_flags(struct json_ctx *ctx, json_t *root,
|
|
- enum table_flags *flags)
|
|
-{
|
|
- json_t *tmp, *tmp2;
|
|
- size_t index;
|
|
- int flag;
|
|
-
|
|
- if (json_unpack(root, "{s:o}", "flags", &tmp))
|
|
- return 0;
|
|
-
|
|
- if (json_is_string(tmp)) {
|
|
- flag = parse_table_flag(json_string_value(tmp));
|
|
- if (flag) {
|
|
- *flags = flag;
|
|
- return 0;
|
|
- }
|
|
- json_error(ctx, "Invalid table flag '%s'.",
|
|
- json_string_value(tmp));
|
|
- return 1;
|
|
- }
|
|
- if (!json_is_array(tmp)) {
|
|
- json_error(ctx, "Unexpected table flags value.");
|
|
- return 1;
|
|
- }
|
|
- json_array_foreach(tmp, index, tmp2) {
|
|
- if (json_is_string(tmp2)) {
|
|
- flag = parse_table_flag(json_string_value(tmp2));
|
|
-
|
|
- if (flag) {
|
|
- *flags |= flag;
|
|
- continue;
|
|
- }
|
|
- }
|
|
- json_error(ctx, "Invalid table flag at index %zu.", index);
|
|
- return 1;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root,
|
|
enum cmd_ops op, enum cmd_obj obj)
|
|
{
|
|
@@ -3029,7 +2836,7 @@ static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root,
|
|
.table.location = *int_loc,
|
|
};
|
|
struct table *table = NULL;
|
|
- enum table_flags flags = 0;
|
|
+ int flags = 0;
|
|
|
|
if (json_unpack_err(ctx, root, "{s:s}",
|
|
"family", &family))
|
|
@@ -3040,9 +2847,10 @@ static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root,
|
|
return NULL;
|
|
|
|
json_unpack(root, "{s:s}", "comment", &comment);
|
|
- if (json_parse_table_flags(ctx, root, &flags))
|
|
- return NULL;
|
|
|
|
+ flags = parse_flags_array(ctx, root, "flags", parse_table_flag);
|
|
+ if (flags < 0)
|
|
+ return NULL;
|
|
} else if (op == CMD_DELETE &&
|
|
json_unpack(root, "{s:s}", "name", &h.table.name) &&
|
|
json_unpack(root, "{s:I}", "handle", &h.handle.id)) {
|
|
@@ -3314,7 +3122,7 @@ static int string_to_nft_object(const char *str)
|
|
return 0;
|
|
}
|
|
|
|
-static int string_to_set_flag(const char *str)
|
|
+static unsigned int string_to_set_flag(const char *str)
|
|
{
|
|
const struct {
|
|
enum nft_set_flags val;
|
|
@@ -3341,6 +3149,7 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
|
|
const char *family = "", *policy;
|
|
json_t *tmp, *stmt_json;
|
|
struct set *set;
|
|
+ int flags;
|
|
|
|
if (json_unpack_err(ctx, root, "{s:s, s:s}",
|
|
"family", &family,
|
|
@@ -3423,23 +3232,16 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
|
|
return NULL;
|
|
}
|
|
}
|
|
- if (!json_unpack(root, "{s:o}", "flags", &tmp)) {
|
|
- json_t *value;
|
|
- size_t index;
|
|
-
|
|
- json_array_foreach(tmp, index, value) {
|
|
- int flag;
|
|
|
|
- if (!json_is_string(value) ||
|
|
- !(flag = string_to_set_flag(json_string_value(value)))) {
|
|
- json_error(ctx, "Invalid set flag at index %zu.", index);
|
|
- set_free(set);
|
|
- handle_free(&h);
|
|
- return NULL;
|
|
- }
|
|
- set->flags |= flag;
|
|
- }
|
|
+ flags = parse_flags_array(ctx, root, "flags", string_to_set_flag);
|
|
+ if (flags < 0) {
|
|
+ json_error(ctx, "Invalid set flags in set '%s'.", h.set.name);
|
|
+ set_free(set);
|
|
+ handle_free(&h);
|
|
+ return NULL;
|
|
}
|
|
+ set->flags |= flags;
|
|
+
|
|
if (!json_unpack(root, "{s:o}", "elem", &tmp)) {
|
|
set->init = json_parse_set_expr(ctx, "elem", tmp);
|
|
if (!set->init) {
|
|
@@ -3624,7 +3426,6 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
|
|
int inv = 0, flags = 0, i, j;
|
|
struct handle h = { 0 };
|
|
struct obj *obj;
|
|
- json_t *jflags;
|
|
|
|
if (json_unpack_err(ctx, root, "{s:s, s:s}",
|
|
"family", &family,
|
|
@@ -3804,13 +3605,12 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
|
|
obj->synproxy.wscale = j;
|
|
obj->synproxy.flags |= NF_SYNPROXY_OPT_MSS;
|
|
obj->synproxy.flags |= NF_SYNPROXY_OPT_WSCALE;
|
|
- if (!json_unpack(root, "{s:o}", "flags", &jflags)) {
|
|
- flags = json_parse_synproxy_flags(ctx, jflags);
|
|
- if (flags < 0)
|
|
- goto err_free_obj;
|
|
+ flags = parse_flags_array(ctx, root, "flags",
|
|
+ json_parse_synproxy_flag);
|
|
+ if (flags < 0)
|
|
+ goto err_free_obj;
|
|
|
|
- obj->synproxy.flags |= flags;
|
|
- }
|
|
+ obj->synproxy.flags |= flags;
|
|
break;
|
|
default:
|
|
BUG("Invalid CMD '%d'", cmd_obj);
|