Blob Blame History Raw
m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [], [
    AT_BANNER([firewall-cmd (FIREWALL_BACKEND)])
])

FWD_START_TEST([basic options])
    AT_KEYWORDS(panic reload)

    FWD_CHECK([-h], 0, ignore)
    FWD_CHECK([--help], 0, ignore)
    FWD_CHECK([-V], 0, ignore)
    FWD_CHECK([--reload], 0, ignore)
    dnl Don't test --complete-reload, it causes modules to unload and we don't
    dnl want to do that to the testing host. The module unload _should_ be
    dnl denied, but lets be safe and avoid it all together.
    dnl
    dnl FWD_CHECK([--complete-reload], 0, ignore)
    FWD_CHECK([--permanent --complete-reload], 2, ignore, ignore)

    FWD_CHECK([--panic-on], 0, ignore)
    FWD_RELOAD
    FWD_CHECK([--query-panic], 0, [yes
])
    FWD_CHECK([--panic-off], 0, ignore)
    FWD_CHECK([--query-panic], 1, [no
])
FWD_END_TEST

FWD_START_TEST([get/list options])
    AT_KEYWORDS(zone service icmp)

    FWD_CHECK([--get-zones], 0, ignore)
    FWD_CHECK([--get-services], 0, ignore)
    FWD_CHECK([--get-icmptypes], 0, ignore)
    FWD_CHECK([--permanent --get-zones], 0, ignore)
    FWD_CHECK([--permanent --get-services], 0, ignore)
    FWD_CHECK([--permanent --get-icmptypes], 0, ignore)

    FWD_CHECK([--list-all-zones], 0, ignore)
    FWD_CHECK([--list-all], 0, ignore)
    FWD_CHECK([--permanent --list-all-zones], 0, ignore)
    FWD_CHECK([--permanent --list-all], 0, ignore)
FWD_END_TEST

FWD_START_TEST([default zone])
    AT_KEYWORDS(zone)

    FWD_CHECK([--get-default-zone], 0, [public
])
    FWD_CHECK([--set-default-zone="home"], 0, ignore)
    FWD_CHECK([--get-default-zone], 0, [home
])
    FWD_CHECK([--set-default-zone="public"], 0, ignore)
    FWD_CHECK([--set-default-zone], 2, ignore, ignore)
FWD_END_TEST

FWD_START_TEST([user zone])
    AT_KEYWORDS(zone)

    FWD_CHECK([--new-zone=foobar], 2, ignore, ignore) dnl no --permanent
    FWD_CHECK([--permanent --new-zone=foobar], 0, ignore)
    FWD_CHECK([--permanent --get-zones | grep foobar], 0, ignore)
    FWD_CHECK([--permanent --zone=foobar --get-target | grep default], 0, ignore)
    FWD_CHECK([--permanent --zone=foobar --set-target=BAD], 110, ignore, ignore)
    FWD_CHECK([--permanent --zone=foobar --set-target=%%REJECT%%], 0, ignore)
    FWD_CHECK([--permanent --zone=foobar --set-target=DROP], 0, ignore)
    FWD_CHECK([--permanent --zone=foobar --set-target=ACCEPT], 0, ignore)
    FWD_CHECK([--permanent --zone=foobar --get-target | grep ACCEPT], 0, ignore)
    FWD_CHECK([--permanent --zone=foobar --add-service=ssh], 0, ignore)

    dnl verify zone name limits (currently 17)
    FWD_CHECK([-q --permanent --new-zone=123456789abcefghi])
    FWD_CHECK([-q --permanent --new-zone=123456789abcefghij], 116, [ignore], [ignore])
FWD_END_TEST([-e '/ERROR: INVALID_TARGET: BAD/d'dnl
              -e '/ERROR: INVALID_NAME: Zone of/d'])

FWD_START_TEST([zone interfaces])
    AT_KEYWORDS(zone)

    FWD_CHECK([--zone=work --add-interface=dummy], 0, ignore)
    FWD_CHECK([--get-zone-of-interface=dummy], 0, [work
])
    FWD_CHECK([--get-active-zones], 0, ignore)
    FWD_CHECK([--zone work --query-interface=dummy], 0, ignore)

    FWD_CHECK([--zone=public --change-interface=dummy], 0, ignore)
    FWD_CHECK([--get-zone-of-interface=dummy], 0, [public
])
    FWD_CHECK([--zone=block --add-interface=dummy1], 0, ignore)
    FWD_CHECK([--zone=block --remove-interface=dummy1], 0, ignore)

    FWD_CHECK([--zone=dmz --change-zone=dummy], 0, ignore)
    FWD_CHECK([--get-zone-of-interface=dummy], 0, [dmz
])
    FWD_CHECK([--zone=dmz --list-interfaces], 0, [dummy
])
    FWD_CHECK([--zone=dmz --remove-interface=dummy], 0, ignore)
    FWD_CHECK([--zone=dmz --query-interface dummy], 1, ignore, ignore)

    FWD_CHECK([--zone=dmz --change-interface=dummy], 0, ignore) dnl functions as an add
    FWD_CHECK([--zone=dmz --query-interface dummy], 0, ignore)
    FWD_CHECK([--zone=dmz --remove-interface=dummy], 0, ignore)

    FWD_CHECK([--zone=dmz --query-interface dummy], 1, ignore, ignore)
    FWD_CHECK([--get-zone-of-interface=dummy], 2, ignore, ignore)
    FWD_CHECK([--get-zone-of-interface], 2, ignore, ignore)
    FWD_CHECK([--zone=dmz --get-zones], 2, ignore, ignore)
    FWD_CHECK([--zone=dmz --get-services], 2, ignore, ignore)
    FWD_CHECK([--zone=dmz --get-default-zone], 2, ignore, ignore)
    FWD_CHECK([--zone=dmz --set-default-zone], 2, ignore, ignore)
    FWD_CHECK([--zone=dmz --get-zone-of-interface], 2, ignore, ignore)

    FWD_CHECK([--permanent --zone=work --add-interface=perm_dummy], 0, ignore)
    FWD_CHECK([--permanent --zone=trusted --add-interface=perm_dummy2], 0, ignore)
    FWD_RELOAD
    FWD_CHECK([--permanent --get-zone-of-interface=perm_dummy], 0, [work
])
    FWD_CHECK([--permanent --zone work --query-interface=perm_dummy], 0, ignore)
    FWD_CHECK([--permanent --zone=work --list-interfaces], 0, [perm_dummy
])

    m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [], [
        FWD_CHECK([--permanent --zone=public --add-interface=perm_dummy], 18, ignore, ignore)
    ])
    FWD_CHECK([--permanent --zone=public --change-interface=perm_dummy], 0, ignore)
    FWD_CHECK([--permanent --get-zone-of-interface=perm_dummy], 0, [public
])
    FWD_CHECK([--permanent --zone=public --remove-interface=perm_dummy], 0, ignore)
    FWD_CHECK([--permanent --zone=public --query-interface perm_dummy], 1, ignore)
    FWD_CHECK([--permanent --zone=public --change-interface=perm_dummy], 0, ignore)
    FWD_CHECK([--permanent --get-zone-of-interface=perm_dummy], 0, [public
])
    FWD_CHECK([--permanent --zone=public --remove-interface=perm_dummy], 0, ignore)
    FWD_CHECK([--permanent --zone=public --query-interface perm_dummy], 1, ignore)
    FWD_CHECK([--permanent --zone=trusted --remove-interface=perm_dummy2], 0, ignore)
    FWD_RELOAD

    FWD_CHECK([--add-interface=foo], 0, ignore)
    FWD_CHECK([--add-interface=bar --zone=public], 0, ignore)
    FWD_CHECK([--set-default-zone=trusted], 0, ignore)
    FWD_CHECK([--get-default-zone], 0, [trusted
])
    dnl check that changing default zone moves interfaces in that zone
    FWD_CHECK([--query-interface foo --zone=trusted], 0, ignore)
    dnl check that *only* iface1 was moved to new default zone
    FWD_CHECK([--query-interface bar --zone=public], 0, ignore)
    FWD_CHECK([--set-default-zone=public], 0, ignore)
    FWD_CHECK([--remove-interface=foo], 0, ignore)
    FWD_CHECK([--remove-interface=bar], 0, ignore)

    dnl exercise wildcards, rhbz 1644025
    dnl Note: This feature is undocumented, because it's a possible security
    dnl risk.
    FWD_CHECK([--zone=trusted --add-interface=+], 0, ignore)
    FWD_CHECK([--add-interface=foobar+++], 0, ignore)
    FWD_CHECK([--add-interface=foobar+], 0, ignore)
    NFT_LIST_RULES([inet], [filter_INPUT_ZONES], 0, [dnl
        table inet firewalld {
            chain filter_INPUT_ZONES {
                iifname "foobar*" goto filter_IN_public
                iifname "foobar++*" goto filter_IN_public
                goto filter_IN_trusted
                goto filter_IN_public
            }
        }
    ])
    FWD_CHECK([--zone=trusted --remove-interface=+], 0, ignore)
    FWD_CHECK([--remove-interface=foobar+++], 0, ignore)
    FWD_CHECK([--remove-interface=foobar+], 0, ignore)
    FWD_CHECK([--permanent --add-interface=foobar+], 0, ignore)
    FWD_CHECK([--permanent --remove-interface=foobar+], 0, ignore)
    FWD_RELOAD
FWD_END_TEST([-e '/ERROR: ZONE_CONFLICT: perm_dummy/d'])

FWD_START_TEST([zone sources])
    AT_KEYWORDS(zone)

    m4_define([check_zone_source], [
        FWD_CHECK([--zone=public --add-source=$1], 0, ignore)
        FWD_CHECK([--get-zone-of-source=$1], 0, [public
])
        FWD_CHECK([--zone=public --list-sources], 0, [$1
])
        FWD_CHECK([--zone=public --list-all | TRIM | grep ^sources], 0, [sources: $1
])
        FWD_CHECK([--get-active-zones | TRIM | grep "^\(public\|sources\)"], 0, [public
sources: $1
])
        FWD_CHECK([--zone public --query-source=$1], 0, ignore)
        FWD_CHECK([--zone=work --change-source=$1], 0, ignore)
        FWD_CHECK([--get-zone-of-source=$1], 0, [work
])
        FWD_CHECK([--zone=work --remove-source=$1], 0, ignore)
        FWD_CHECK([--zone work --query-source=$1], 1, ignore)
        FWD_CHECK([--get-zone-of-source=$1], 2, ignore, ignore)
        FWD_CHECK([--get-zone-of-source], 2, ignore, ignore) dnl missing arg
        FWD_CHECK([--permanent --zone=public --add-source=$1], 0, ignore)
        FWD_CHECK([--permanent --get-zone-of-source=$1], 0, [public
])
        FWD_CHECK([--permanent --zone=public --list-sources], 0, [$1
])
        FWD_CHECK([--permanent --zone=public --list-all | TRIM | grep ^sources], 0, [sources: $1
])
        FWD_CHECK([--permanent --zone public --query-source=$1], 0, ignore)

        m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [], [
            FWD_CHECK([--permanent --zone=work --add-source=$1], 18, ignore, ignore)
        ])
        FWD_CHECK([--permanent --zone=work --change-source=$1], 0, ignore)
        FWD_CHECK([--permanent --get-zone-of-source=$1], 0, [work
])
        FWD_CHECK([--permanent --zone=work --remove-source=$1], 0, ignore)
        FWD_CHECK([--permanent --zone work --query-source=$1], 1, ignore)
    ])

    check_zone_source([1.2.3.4])
    check_zone_source([192.168.1.0/24])
    IF_HOST_SUPPORTS_IPV6_RULES([
    check_zone_source([3ffe:501:ffff::/64])
    check_zone_source([dead:beef::babe])
    ])

    m4_undefine([check_zone_source])

FWD_END_TEST([ -e '/ERROR: ZONE_CONFLICT/d'])

FWD_START_TEST([services])
    AT_KEYWORDS(service)

    FWD_CHECK([--add-service=dns --timeout 60 --zone=public], 0, ignore)
    FWD_CHECK([--query-service dns], 0, ignore)
    FWD_CHECK([--remove-service=dns], 0, ignore)
    FWD_CHECK([--query-service=dns], 1, ignore)
    FWD_CHECK([--add-service=smtpssssssss], 101, ignore, ignore)
    FWD_CHECK([--add-service=dns --timeout], 2, ignore, ignore) dnl missing argument
    FWD_CHECK([--add-service=dns --add-interface=dummy0], 2, ignore, ignore) dnl impossible combination

    FWD_CHECK([--permanent --zone=external --add-service=dns --timeout 60], 2, ignore, ignore) dnl impossible combination
    FWD_CHECK([--permanent --zone=external --add-service dns], 0, ignore)
    FWD_CHECK([--permanent --zone=external --list-services], 0, [dns ssh
])
    FWD_CHECK([--permanent --zone=external --query-service dns], 0, ignore)
    m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [
        FWD_CHECK([--permanent --zone=external --remove-service-from-zone=dns], 0, ignore)
    ], [
        FWD_CHECK([--permanent --zone=external --remove-service=dns], 0, ignore)
    ])
    FWD_CHECK([--permanent --zone=external --query-service=dns], 1, ignore)
    FWD_CHECK([--permanent --zone=external --add-service=smtpssssssss], 101, ignore, ignore)
    FWD_CHECK([--permanent --zone=external --add-service=dns --add-interface=dummy0], 2, ignore, ignore) dnl impossible combination

    FWD_CHECK([--add-service=http --add-service=nfs --timeout=1h], 0, ignore)
    FWD_CHECK([--query-service http], 0, ignore)
    FWD_CHECK([--query-service=nfs --zone=public], 0, ignore)
    FWD_CHECK([--remove-service=nfs --remove-service=http], 0, ignore)
    FWD_CHECK([--query-service http], 1, ignore)
    FWD_CHECK([--query-service nfs], 1, ignore)

    FWD_CHECK([--permanent --add-service=http --add-service=nfs], 0, ignore)
    FWD_CHECK([--permanent --query-service http], 0, ignore)
    FWD_CHECK([--permanent --query-service=nfs --zone=public], 0, ignore)
    m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [
        FWD_CHECK([--permanent --remove-service-from-zone=nfs --remove-service-from-zone=http], 0, ignore)
    ], [
        FWD_CHECK([--permanent --remove-service=nfs --remove-service=http], 0, ignore)
    ])
    FWD_CHECK([--permanent  --query-service http], 1, ignore)
    FWD_CHECK([--permanent  --query-service nfs], 1, ignore)
FWD_END_TEST([-e '/ERROR: INVALID_SERVICE:/d'])

FWD_START_TEST([user services])
    AT_KEYWORDS(service)

    FWD_CHECK([--permanent --new-service=ssh], 26, ignore, ignore) dnl already exists

    FWD_CHECK([--permanent --new-service=foobar], 0, ignore)
    FWD_CHECK([--permanent --get-services | grep foobar], 0, ignore)

    FWD_CHECK([--permanent --service=foobar --add-port=666], 102, ignore, ignore) dnl no protocol
    FWD_CHECK([--permanent --service=foobar --add-port=666/dummy], 103, ignore, ignore) dnl bad protocol
    FWD_CHECK([--permanent --service=foobar --add-port=666/tcp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-port=666/tcp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --add-port=111-222/udp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-port=111-222/udp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-port 111-222/udp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-port=111-222/udp], 1, ignore)
    FWD_CHECK([--permanent --service=foobar --add-port=666/sctp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-port=666/sctp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-port 666/sctp], 0, ignore, ignore)
    FWD_CHECK([--permanent --service=foobar --query-port=666/sctp], 1, ignore)
    FWD_CHECK([--permanent --service=foobar --add-port=999/dccp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-port=999/dccp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-port 999/dccp], 0, ignore, ignore)
    FWD_CHECK([--permanent --service=foobar --query-port=999/dccp], 1, ignore)
    FWD_CHECK([--permanent --service=foobar --add-port=666/sctp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --add-port=999/dccp], 0, ignore)

    FWD_CHECK([--permanent --service=foobar --add-protocol=ddp --add-protocol gre], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-protocol=ddp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-protocol=gre], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-protocol ddp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-protocol gre], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-protocol=ddp], 1, ignore)
    FWD_CHECK([--permanent --service=foobar --query-protocol=gre], 1, ignore)

    FWD_CHECK([--permanent --service=foobar --add-module=sip], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-module=sip], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --add-module=ftp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-module=ftp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-module=ftp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-module=ftp], 1, ignore)

    FWD_CHECK([--permanent --service=foobar --add-helper=sip], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-helper=sip], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --add-helper=ftp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-helper=ftp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --get-service-helpers], 0, [dnl
ftp
])
    FWD_CHECK([--permanent --service=foobar --remove-helper=ftp], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-helper=ftp], 1, ignore)

    FWD_CHECK([--permanent --service=foobar --set-destination=ipv4], 121, ignore, ignore) dnl no address
    FWD_CHECK([--permanent --service=foobar --set-destination=ipv4:foo], 105, ignore, ignore) dnl bad address
    FWD_CHECK([--permanent --service=foobar --set-destination=ipv4:1.2.3.4], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-destination=ipv4], 0, ignore)
    IF_HOST_SUPPORTS_IPV6_RULES([
    FWD_CHECK([--permanent --service=foobar --set-destination=ipv6:fd00:dead:beef:ff0::/64], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-destination=ipv6:fd00:dead:beef:ff0::/64], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --remove-destination=ipv6], 0, ignore)
    FWD_CHECK([--permanent --service=foobar --query-destination=ipv6:fd00:dead:beef:ff0::/64], 1, ignore)
    ])

    FWD_CHECK([--permanent --zone=public --add-service=foobar], 0, ignore)
    FWD_CHECK([--permanent --zone=public --list-services | grep foobar], 0, ignore)
    FWD_CHECK([--permanent --delete-service=foobar], 0, ignore)
    FWD_CHECK([--permanent --zone=public --list-services | grep foobar], 1, ignore)

    AT_DATA([./foobar-to-be-renamed], [m4_strip([dnl
        <?xml version="1.0" encoding="utf-8"?>
        <service>
        <protocol value="icmp" />
        <port protocol="tcp" port="1234" />
        </service>
    ])
    FWD_CHECK([--permanent --new-service-from-file="./foobar-to-be-renamed" --name="foobar-from-file"])
    FWD_CHECK([--permanent --get-services | grep foobar-from-file], 0, [ignore])
])

FWD_END_TEST([-e '/ERROR: NAME_CONFLICT: new_service():/d' dnl
              -e '/ERROR: INVALID_ADDR:/d'])

FWD_START_TEST([ports])
    AT_KEYWORDS(port)

    FWD_CHECK([--zone home --list-ports], 0, ignore)
    FWD_CHECK([--add-port=666], 102, ignore, ignore) dnl no protocol
    FWD_CHECK([--add-port=666/dummy], 103, ignore, ignore) dnl bad protocol
    FWD_CHECK([--add-port 122/udpa --add-port 122/udpp --add-port 8745897/foo], 254, ignore, ignore)
    FWD_CHECK([--add-port 122/udpa --add-port 122/udpp --add-port 8745897/foo --add-port bar], 254, ignore, ignore)
    FWD_CHECK([--add-port=666/tcp --zone=public --timeout=30m], 0, ignore)
    FWD_CHECK([--remove-port=666/tcp], 0, ignore)
    FWD_CHECK([--add-port=111-222/udp], 0, ignore)
    FWD_CHECK([--query-port=111-222/udp --zone=public], 0, ignore)
    FWD_CHECK([--remove-port 111-222/udp], 0, ignore)
    FWD_CHECK([--query-port=111-222/udp], 1, ignore)

    FWD_CHECK([--add-port=5000/sctp], 0, ignore)
    FWD_CHECK([--query-port=5000/sctp --zone=public], 0, ignore)
    FWD_CHECK([--remove-port 5000/sctp], 0, ignore)
    FWD_CHECK([--query-port=5000/sctp], 1, ignore)
    FWD_CHECK([--add-port=222/dccp], 0, ignore)
    FWD_CHECK([--query-port=222/dccp --zone=public], 0, ignore)
    FWD_CHECK([--remove-port 222/dccp], 0, ignore)
    FWD_CHECK([--query-port=222/dccp], 1, ignore)

    FWD_CHECK([--permanent --add-port=666], 102, ignore, ignore) dnl no protocol
    FWD_CHECK([--permanent --add-port=666/dummy], 103, ignore, ignore) dnl bad protocol
    FWD_CHECK([--permanent --add-port=666/tcp], 0, ignore)
    FWD_CHECK([--permanent --remove-port=666/tcp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --add-port=111-222/udp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --query-port=111-222/udp], 0, ignore)
    FWD_CHECK([--permanent --remove-port 111-222/udp], 0, ignore)
    FWD_CHECK([--permanent --query-port=111-222/udp], 1, ignore)

    FWD_CHECK([--permanent --add-port=5000/sctp], 0, ignore)
    FWD_CHECK([--permanent --query-port=5000/sctp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --remove-port 5000/sctp], 0, ignore)
    FWD_CHECK([--permanent --query-port=5000/sctp], 1, ignore)
    FWD_CHECK([--permanent --add-port=222/dccp], 0, ignore)
    FWD_CHECK([--permanent --query-port=222/dccp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --remove-port 222/dccp], 0, ignore)
    FWD_CHECK([--permanent --query-port=222/dccp], 1, ignore)

    FWD_CHECK([--add-port=80/tcp --add-port 443-444/udp], 0, ignore)
    FWD_CHECK([--query-port=80/tcp --zone=public], 0, ignore)
    FWD_CHECK([--query-port=443-444/udp], 0, ignore)
    FWD_CHECK([--remove-port 80/tcp --remove-port=443-444/udp], 0, ignore)
    FWD_CHECK([--query-port=80/tcp], 1, ignore)
    FWD_CHECK([--query-port=443-444/udp], 1, ignore)

    FWD_CHECK([--permanent --add-port=80/tcp --add-port 443-444/udp], 0, ignore)
    FWD_CHECK([--permanent --query-port=80/tcp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --query-port=443-444/udp], 0, ignore)
    FWD_CHECK([--permanent --remove-port 80/tcp --remove-port=443-444/udp], 0, ignore)
    FWD_CHECK([--permanent --query-port=80/tcp], 1, ignore)
    FWD_CHECK([--permanent --query-port=443-444/udp], 1, ignore)
FWD_END_TEST

FWD_START_TEST([source ports])
    AT_KEYWORDS(port)

    FWD_CHECK([--zone home --list-source-ports], 0, ignore)
    FWD_CHECK([--add-source-port=666], 102, ignore, ignore) dnl no protocol
    FWD_CHECK([--add-source-port=666/dummy], 103, ignore, ignore) dnl bad protocol
    FWD_CHECK([--add-source-port=666/tcp --zone=public --timeout=30m], 0, ignore)
    FWD_CHECK([--remove-source-port=666/tcp], 0, ignore)
    FWD_CHECK([--add-source-port=111-222/udp], 0, ignore)
    FWD_CHECK([--query-source-port=111-222/udp --zone=public], 0, ignore)
    FWD_CHECK([--remove-source-port 111-222/udp], 0, ignore)
    FWD_CHECK([--query-source-port=111-222/udp], 1, ignore)

    FWD_CHECK([--permanent --add-source-port=666], 102, ignore, ignore) dnl no protocol
    FWD_CHECK([--permanent --add-source-port=666/dummy], 103, ignore, ignore) dnl bad protocol
    FWD_CHECK([--permanent --add-source-port=666/tcp], 0, ignore)
    FWD_CHECK([--permanent --remove-source-port=666/tcp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --add-source-port=111-222/udp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --query-source-port=111-222/udp], 0, ignore)
    FWD_CHECK([--permanent --remove-source-port 111-222/udp], 0, ignore)
    FWD_CHECK([--permanent --query-source-port=111-222/udp], 1, ignore)

    FWD_CHECK([--add-source-port=80/tcp --add-source-port 443-444/udp], 0, ignore)
    FWD_CHECK([--query-source-port=80/tcp --zone=public], 0, ignore)
    FWD_CHECK([--query-source-port=443-444/udp], 0, ignore)
    FWD_CHECK([--remove-source-port 80/tcp --remove-source-port=443-444/udp], 0, ignore)
    FWD_CHECK([--query-source-port=80/tcp], 1, ignore)
    FWD_CHECK([--query-source-port=443-444/udp], 1, ignore)

    FWD_CHECK([--permanent --add-source-port=80/tcp --add-source-port 443-444/udp], 0, ignore)
    FWD_CHECK([--permanent --query-source-port=80/tcp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --query-source-port=443-444/udp], 0, ignore)
    FWD_CHECK([--permanent --remove-source-port 80/tcp --remove-source-port=443-444/udp], 0, ignore)
    FWD_CHECK([--permanent --query-source-port=80/tcp], 1, ignore)
    FWD_CHECK([--permanent --query-source-port=443-444/udp], 1, ignore)
FWD_END_TEST

FWD_START_TEST([protocols])
    AT_KEYWORDS(protocol)

    FWD_CHECK([--add-protocol=dummy], 103, ignore, ignore)
    FWD_CHECK([--add-protocol=dccp --zone=public], 0, ignore)
    FWD_CHECK([--query-protocol=dccp], 0, ignore)
    FWD_CHECK([--remove-protocol dccp], 0, ignore)
    FWD_CHECK([--query-protocol=dccp], 1, ignore)
    FWD_CHECK([--permanent --add-protocol=dummy], 103, ignore, ignore)
    FWD_CHECK([--permanent --add-protocol=dccp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --query-protocol=dccp], 0, ignore)
    FWD_CHECK([--permanent --remove-protocol dccp], 0, ignore)
    FWD_CHECK([--permanent --query-protocol=dccp], 1, ignore)

    FWD_CHECK([--add-protocol=ddp --add-protocol gre], 0, ignore)
    FWD_CHECK([--query-protocol=ddp --zone=public], 0, ignore)
    FWD_CHECK([--query-protocol=gre], 0, ignore)
    FWD_CHECK([--remove-protocol ddp --remove-protocol=gre], 0, ignore)
    FWD_CHECK([--query-protocol=ddp], 1, ignore)
    FWD_CHECK([--query-protocol=gre], 1, ignore)
    FWD_CHECK([--permanent --add-protocol=ddp --add-protocol gre], 0, ignore)
    FWD_CHECK([--permanent --query-protocol=ddp --zone=public], 0, ignore)
    FWD_CHECK([--permanent --query-protocol=gre], 0, ignore)
    FWD_CHECK([--permanent --remove-protocol ddp --remove-protocol=gre], 0, ignore)
    FWD_CHECK([--permanent --query-protocol=ddp], 1, ignore)
    FWD_CHECK([--permanent --query-protocol=gre], 1, ignore)
FWD_END_TEST([-e '/ERROR: INVALID_PROTOCOL: dummy/d'])

FWD_START_TEST([masquerade])
    AT_KEYWORDS(masquerade nat)

    FWD_CHECK([--add-masquerade --zone=public], 0, ignore)
    dnl man page says this should only affect IPv4, so verify that.
    NFT_LIST_RULES([ip], [nat_POST_public_allow], 0, [dnl
        table ip firewalld {
            chain nat_POST_public_allow {
                oifname != "lo" masquerade
            }
        }
    ])
    NFT_LIST_RULES([ip6], [nat_POST_public_allow], 0, [dnl
        table ip6 firewalld {
            chain nat_POST_public_allow {
            }
        }
    ])
    IPTABLES_LIST_RULES([nat], [POST_public_allow], 0, [dnl
        MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0
    ])
    IP6TABLES_LIST_RULES([nat], [POST_public_allow], 0, [dnl
    ])
    FWD_CHECK([--query-masquerade], 0, ignore)
    FWD_CHECK([--remove-masquerade], 0, ignore)
    FWD_CHECK([--query-masquerade], 1, ignore)

    FWD_CHECK([--permanent --add-masquerade --zone=public], 0, ignore)
    FWD_CHECK([--permanent --query-masquerade], 0, ignore)
    FWD_CHECK([--permanent --remove-masquerade], 0, ignore)
    FWD_CHECK([--permanent --query-masquerade], 1, ignore)
FWD_END_TEST

FWD_START_TEST([forward ports])
    AT_KEYWORDS(port forward_port)

    FWD_CHECK([--add-forward-port=666], 106, ignore, ignore)
    FWD_CHECK([--add-forward-port=port=11:proto=tcp:toport=22], 0, ignore)
    dnl man page says this should only affect IPv4, so verify that.
    NFT_LIST_RULES([ip], [nat_PRE_public_allow], 0, [dnl
        table ip firewalld {
            chain nat_PRE_public_allow {
                tcp dport 11 redirect to :22
            }
        }
    ])
    NFT_LIST_RULES([ip6], [nat_PRE_public_allow], 0, [dnl
        table ip6 firewalld {
            chain nat_PRE_public_allow {
            }
        }
    ])
    IPTABLES_LIST_RULES([nat], [PRE_public_allow], 0, [dnl
        DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:11 to::22
    ])
    IP6TABLES_LIST_RULES([nat], [PRE_public_allow], 0, [dnl
    ])
    FWD_CHECK([--remove-forward-port=port=11:proto=tcp:toport=22 --zone=public], 0, ignore)
    FWD_CHECK([--add-forward-port=port=33:proto=tcp:toaddr=4444], 105, ignore, ignore) dnl bad address
    FWD_CHECK([--add-forward-port=port=33:proto=tcp:toaddr=4.4.4.4 --zone=public], 0, ignore)
    dnl man page says this should only affect IPv4, so verify that.
    NFT_LIST_RULES([ip], [nat_PRE_public_allow], 0, [dnl
        table ip firewalld {
            chain nat_PRE_public_allow {
                tcp dport 33 dnat to 4.4.4.4
            }
        }
    ])
    NFT_LIST_RULES([ip6], [nat_PRE_public_allow], 0, [dnl
        table ip6 firewalld {
            chain nat_PRE_public_allow {
            }
        }
    ])
    IPTABLES_LIST_RULES([nat], [PRE_public_allow], 0, [dnl
        DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:33 to:4.4.4.4
    ])
    IP6TABLES_LIST_RULES([nat], [PRE_public_allow], 0, [dnl
    ])
    FWD_CHECK([--remove-forward-port=port=33:proto=tcp:toaddr=4.4.4.4], 0, ignore)
    FWD_CHECK([--add-forward-port=port=55:proto=tcp:toport=66:toaddr=7.7.7.7], 0, ignore)
    FWD_CHECK([--query-forward-port port=55:proto=tcp:toport=66:toaddr=7.7.7.7 --zone=public], 0, ignore)
    FWD_CHECK([--remove-forward-port=port=55:proto=tcp:toport=66:toaddr=7.7.7.7], 0, ignore)
    FWD_CHECK([--query-forward-port=port=55:proto=tcp:toport=66:toaddr=7.7.7.7], 1, ignore)
    FWD_CHECK([--add-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7], 0, ignore)
    FWD_CHECK([--query-forward-port port=66:proto=sctp:toport=66:toaddr=7.7.7.7 --zone=public], 0, ignore)
    FWD_CHECK([--remove-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7], 0, ignore)
    FWD_CHECK([--query-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7], 1, ignore)
    IF_HOST_SUPPORTS_IPV6_RULES([
    FWD_CHECK([--add-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::], 0, ignore)
    dnl this should only affect IPv6, so verify that.
    NFT_LIST_RULES([ip], [nat_PRE_public_allow], 0, [dnl
        table ip firewalld {
            chain nat_PRE_public_allow {
            }
        }
    ])
    NFT_LIST_RULES([ip6], [nat_PRE_public_allow], 0, [dnl
        table ip6 firewalld {
            chain nat_PRE_public_allow {
                sctp dport 66 dnat to [[fd00:dead:beef:ff0::]:66]
            }
        }
    ])
    IPTABLES_LIST_RULES([nat], [PRE_public_allow], 0, [dnl
    ])
    IP6TABLES_LIST_RULES([nat], [PRE_public_allow], 0, [dnl
        DNAT sctp ::/0 ::/0 sctp dpt:66 [to:[fd00:dead:beef:ff0::]:66]
    ])
    FWD_CHECK([--query-forward-port port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0:: --zone=public], 0, ignore)
    FWD_CHECK([--remove-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::], 0, ignore)
    FWD_CHECK([--query-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::], 1, ignore)
    ])
    FWD_CHECK([--add-forward-port=port=88:proto=udp:toport=99 --add-forward-port port=100:proto=tcp:toport=200], 0, ignore)
    FWD_CHECK([--query-forward-port=port=100:proto=tcp:toport=200], 0, ignore)
    FWD_CHECK([--query-forward-port=port=88:proto=udp:toport=99 --zone=public], 0, ignore)
    FWD_CHECK([--remove-forward-port port=100:proto=tcp:toport=200 --remove-forward-port=port=88:proto=udp:toport=99], 0, ignore)
    FWD_CHECK([--query-forward-port port=100:proto=tcp:toport=200], 1, ignore)
    FWD_CHECK([--query-forward-port=port=88:proto=udp:toport=99], 1, ignore)
    FWD_CHECK([--list-forward-ports], 0, ignore)

    FWD_CHECK([--permanent --add-forward-port=666], 106, ignore, ignore)
    FWD_CHECK([--permanent --add-forward-port=port=11:proto=tcp:toport=22], 0, ignore)
    FWD_CHECK([--permanent --remove-forward-port=port=11:proto=tcp:toport=22 --zone=public], 0, ignore)
    FWD_CHECK([--permanent --add-forward-port=port=33:proto=tcp:toaddr=4444], 105, ignore, ignore) dnl bad address
    FWD_CHECK([--permanent --add-forward-port=port=33:proto=tcp:toaddr=4.4.4.4 --zone=public], 0, ignore)
    FWD_CHECK([--permanent --remove-forward-port=port=33:proto=tcp:toaddr=4.4.4.4], 0, ignore)
    FWD_CHECK([--permanent --add-forward-port=port=55:proto=tcp:toport=66:toaddr=7.7.7.7], 0, ignore)
    FWD_CHECK([--permanent --query-forward-port port=55:proto=tcp:toport=66:toaddr=7.7.7.7 --zone=public], 0, ignore)
    FWD_CHECK([--permanent --remove-forward-port=port=55:proto=tcp:toport=66:toaddr=7.7.7.7], 0, ignore)
    FWD_CHECK([--permanent --query-forward-port=port=55:proto=tcp:toport=66:toaddr=7.7.7.7], 1, ignore)
    FWD_CHECK([--permanent --add-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7], 0, ignore)
    FWD_CHECK([--permanent --query-forward-port port=66:proto=sctp:toport=66:toaddr=7.7.7.7 --zone=public], 0, ignore)
    FWD_CHECK([--permanent --remove-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7], 0, ignore)
    FWD_CHECK([--permanent --query-forward-port=port=66:proto=sctp:toport=66:toaddr=7.7.7.7], 1, ignore)
    IF_HOST_SUPPORTS_IPV6_RULES([
    FWD_CHECK([--permanent --add-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::], 0, ignore)
    FWD_CHECK([--permanent --query-forward-port port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0:: --zone=public], 0, ignore)
    FWD_CHECK([--permanent --remove-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::], 0, ignore)
    FWD_CHECK([--permanent --query-forward-port=port=66:proto=sctp:toport=66:toaddr=fd00:dead:beef:ff0::], 1, ignore)
    ])
    FWD_CHECK([--permanent --add-forward-port=port=88:proto=udp:toport=99 --add-forward-port port=100:proto=tcp:toport=200], 0, ignore)
    FWD_CHECK([--permanent --query-forward-port=port=100:proto=tcp:toport=200], 0, ignore)
    FWD_CHECK([--permanent --query-forward-port=port=88:proto=udp:toport=99 --zone=public], 0, ignore)
    FWD_CHECK([--permanent --remove-forward-port port=100:proto=tcp:toport=200 --remove-forward-port=port=88:proto=udp:toport=99], 0, ignore)
    FWD_CHECK([--permanent --query-forward-port port=100:proto=tcp:toport=200], 1, ignore)
    FWD_CHECK([--permanent --query-forward-port=port=88:proto=udp:toport=99], 1, ignore)
    FWD_CHECK([--permanent --list-forward-ports], 0, ignore)
FWD_END_TEST([-e '/ERROR: Failed to write to file .*\/proc\/sys\/net\/ipv6\/conf\/all\/forwarding.*/d'])

FWD_START_TEST([ICMP block])
    AT_KEYWORDS(icmp)

    FWD_CHECK([--list-icmp-blocks], 0, ignore)

    FWD_CHECK([--zone=external --add-icmp-block=dummyblock], 107, ignore, ignore)
    FWD_CHECK([--zone=external --add-icmp-block=redirect], 0, ignore)
    FWD_CHECK([--zone=external --query-icmp-block=redirect], 0, ignore)
    FWD_CHECK([--zone=external --remove-icmp-block redirect], 0, ignore)
    FWD_CHECK([--zone=external --query-icmp-block=redirect], 1, ignore)
    FWD_CHECK([--permanent --zone=external --add-icmp-block=dummyblock], 107, ignore, ignore)
    FWD_CHECK([--permanent --zone=external --add-icmp-block=redirect], 0, ignore)
    FWD_CHECK([--permanent --zone=external --query-icmp-block=redirect], 0, ignore)
    FWD_CHECK([--permanent --zone=external --remove-icmp-block redirect], 0, ignore)
    FWD_CHECK([--permanent --zone=external --query-icmp-block=redirect], 1, ignore)

    FWD_CHECK([--add-icmp-block-inversion --zone=public], 0, ignore)
    FWD_CHECK([--query-icmp-block-inversion], 0, ignore)
    FWD_CHECK([--remove-icmp-block-inversion], 0, ignore)
    FWD_CHECK([--query-icmp-block-inversion], 1, ignore)
    FWD_CHECK([--permanent --add-icmp-block-inversion --zone=public], 0, ignore)
    FWD_CHECK([--permanent --query-icmp-block-inversion], 0, ignore)
    FWD_CHECK([--permanent --remove-icmp-block-inversion], 0, ignore)
    FWD_CHECK([--permanent --query-icmp-block-inversion], 1, ignore)

    FWD_CHECK([--add-icmp-block-inversion --zone=block], 0, ignore)
    FWD_CHECK([--remove-icmp-block-inversion --zone=block], 0, ignore)
    FWD_CHECK([--add-icmp-block-inversion --zone=drop], 0, ignore)
    FWD_CHECK([--remove-icmp-block-inversion --zone=drop], 0, ignore)
    FWD_CHECK([--add-icmp-block-inversion --zone=trusted], 0, ignore)
    FWD_CHECK([--remove-icmp-block-inversion --zone=trusted], 0, ignore)

    FWD_CHECK([--zone=external --add-icmp-block=echo-reply --add-icmp-block=router-solicitation], 0, ignore)
    FWD_CHECK([--zone=external --query-icmp-block=echo-reply], 0, ignore)
    FWD_CHECK([--zone=external --query-icmp-block=router-solicitation], 0, ignore)
    FWD_CHECK([--zone=external --remove-icmp-block echo-reply --remove-icmp-block=router-solicitation], 0, ignore)
    FWD_CHECK([--zone=external --query-icmp-block=echo-reply], 1, ignore)
    FWD_CHECK([--zone=external --query-icmp-block=router-solicitation], 1, ignore)
    FWD_CHECK([--permanent --zone=external --add-icmp-block=echo-reply --add-icmp-block=router-solicitation], 0, ignore)
    FWD_CHECK([--permanent --zone=external --query-icmp-block=echo-reply], 0, ignore)
    FWD_CHECK([--permanent --zone=external --query-icmp-block=router-solicitation], 0, ignore)
    FWD_CHECK([--permanent --zone=external --remove-icmp-block echo-reply --remove-icmp-block=router-solicitation], 0, ignore)
    FWD_CHECK([--permanent --zone=external --query-icmp-block=echo-reply], 1, ignore)
    FWD_CHECK([--permanent --zone=external --query-icmp-block=router-solicitation], 1, ignore)
FWD_END_TEST([-e '/ERROR: INVALID_ICMPTYPE:/d'])

FWD_START_TEST([user ICMP types])
    AT_KEYWORDS(icmp)

    FWD_CHECK([--permanent --new-icmptype=redirect], 26, ignore, ignore) dnl already exists

    FWD_CHECK([--permanent --new-icmptype=foobar], 0, ignore)
    FWD_CHECK([--permanent --get-icmptypes | grep foobar], 0, ignore)

    FWD_CHECK([--permanent --icmptype=foobar --add-destination=ipv5], 111, ignore, ignore)
    FWD_CHECK([--permanent --icmptype=foobar --add-destination=ipv4], 0, ignore, ignore)
    FWD_CHECK([--permanent --icmptype=foobar --remove-destination=ipv4], 0, ignore)
    FWD_CHECK([--permanent --icmptype=foobar --add-destination=ipv4], 0, ignore)
    FWD_CHECK([--permanent --icmptype=foobar --query-destination=ipv4], 0, ignore)
    FWD_CHECK([--permanent --icmptype=foobar --remove-destination=ipv4], 0, ignore)
    FWD_CHECK([--permanent --icmptype=foobar --query-destination=ipv4], 1, ignore)

    FWD_CHECK([--permanent --zone=public --add-icmp-block=foobar], 0, ignore)
    FWD_CHECK([--permanent --zone=public --list-icmp-blocks | grep foobar], 0, ignore)

    FWD_CHECK([--permanent --delete-icmptype=foobar], 0, ignore)
    FWD_CHECK([--permanent --zone=public --list-icmp-blocks | grep foobar], 1, ignore)
FWD_END_TEST([-e '/NAME_CONFLICT: new_icmptype():/d'])

FWD_START_TEST([ipset])
    AT_KEYWORDS(ipset rhbz1685256)

    CHECK_IPSET
    CHECK_IPSET_HASH_MAC

    dnl Expected test results assume this is set to "no"
    AT_CHECK([sed -i 's/^AllowZoneDrifting.*/AllowZoneDrifting=no/' ./firewalld.conf])
    FWD_RELOAD

    FWD_CHECK([--permanent --new-ipset=foobar --type=hash:ip], 0, ignore)
    FWD_CHECK([--reload], 0, ignore)
    FWD_CHECK([--ipset=foobar --get-entries], 0, [
])
    FWD_CHECK([--ipset=foobar --add-entry=1.2.3.4], 0, ignore)
    FWD_CHECK([--ipset=foobar --get-entries | grep "1.2.3.4"], 0, ignore)
    FWD_CHECK([--ipset=foobar --add-entry=1.2.3.400], 136, ignore, ignore)
    FWD_CHECK([--ipset=foobar --remove-entry=1.2.3.4], 0, ignore)
    FWD_CHECK([--ipset=foobar --get-entries], 0, [
])

    FWD_CHECK([--zone=public --add-source=ipset:foobar], 0, ignore)
    FWD_CHECK([--get-zone-of-source=ipset:foobar | grep public], 0, ignore)
    FWD_CHECK([--zone=public --list-sources | grep "ipset:foobar"], 0, ignore)
    FWD_CHECK([--zone=public --query-source=ipset:foobar], 0, ignore)
    FWD_CHECK([--zone=public --remove-source=ipset:foobar], 0, ignore)
    FWD_CHECK([--zone=public --query-source=ipset:foobar], 1, ignore)

    FWD_CHECK([--permanent --delete-ipset=foobar], 0, ignore)
    FWD_CHECK([--reload], 0, ignore)

    dnl multi dimensional sets
    FWD_CHECK([--permanent --new-ipset=foobar --type=hash:ip,port], 0, ignore)
    FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.10,1234], 0, ignore)
    FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.10,2000-2100], 0, ignore)
    FWD_RELOAD
    NFT_LIST_SET([foobar], 0, [dnl
        table inet firewalld {
            set foobar {
                type ipv4_addr . inet_proto . inet_service
                flags interval
                elements = { 10.10.10.10 . tcp . 1234,
                             10.10.10.10 . tcp . 2000-2100 }
            }
        }
    ])
    FWD_CHECK([--ipset=foobar --add-entry=1.2.3.4,8080], 0, ignore)
    FWD_CHECK([--permanent --delete-ipset=foobar], 0, ignore)
    FWD_RELOAD

    dnl multi dimensional set with non default protocol
    FWD_CHECK([--permanent --new-ipset=foobar --type=hash:ip,port], 0, ignore)
    FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.10,sctp:1234], 0, ignore)
    FWD_RELOAD
    FWD_CHECK([--ipset=foobar --add-entry=20.20.20.20,8080], 0, ignore)
    FWD_CHECK([--zone internal --add-source=ipset:foobar], 0, ignore)
    NFT_LIST_SET([foobar], 0, [dnl
        table inet firewalld {
            set foobar {
                type ipv4_addr . inet_proto . inet_service
                flags interval
                elements = { 10.10.10.10 . sctp . 1234,
                             20.20.20.20 . tcp . 8080 }
            }
        }
    ])
    NFT_LIST_RULES([inet], [filter_INPUT_ZONES], 0, [dnl
        table inet firewalld {
            chain filter_INPUT_ZONES {
                ip saddr . meta l4proto . th sport @foobar goto filter_IN_internal
                goto filter_IN_public
            }
        }
    ])
    IPSET_LIST_SET([foobar], 0, [dnl
        Name: foobar
        Type: hash:ip,port
        Members:
        10.10.10.10,sctp:1234
        20.20.20.20,tcp:8080
    ])
    FWD_CHECK([--ipset=foobar --add-entry=1.2.3.4,sctp:8080], 0, ignore)
    FWD_CHECK([--permanent --delete-ipset=foobar], 0, ignore)
    FWD_RELOAD

    dnl hash:ip,mark
    FWD_CHECK([--permanent --new-ipset=foobar --type=hash:ip,mark], 0, ignore)
    FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.10,0x100], 0, ignore)
    FWD_RELOAD
    FWD_CHECK([--ipset=foobar --add-entry=20.20.20.20,0x200], 0, ignore)
    FWD_CHECK([--zone internal --add-source=ipset:foobar], 0, ignore)
    NFT_LIST_SET([foobar], 0, [dnl
        table inet firewalld {
            set foobar {
                type ipv4_addr . mark
                elements = { 10.10.10.10 . 0x00000100,
                             20.20.20.20 . 0x00000200 }
            }
        }
    ])
    NFT_LIST_RULES([inet], [filter_INPUT_ZONES], 0, [dnl
        table inet firewalld {
            chain filter_INPUT_ZONES {
                ip saddr . mark @foobar goto filter_IN_internal
                goto filter_IN_public
            }
        }
    ])
    IPSET_LIST_SET([foobar], 0, [dnl
        Name: foobar
        Type: hash:ip,mark
        Members:
        10.10.10.10,0x00000100
        20.20.20.20,0x00000200
    ])
    FWD_CHECK([--permanent --delete-ipset=foobar], 0, ignore)
    FWD_RELOAD

    dnl multi dimensional set with intervals
    FWD_CHECK([--permanent --new-ipset=foobar --type=hash:net,port], 0, ignore)
    FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.0/24,sctp:1234], 0, ignore)
    FWD_RELOAD
    FWD_CHECK([--ipset=foobar --add-entry=1.2.3.4,tcp:8080], 0, ignore)
    FWD_CHECK([--permanent --delete-ipset=foobar], 0, ignore)
    FWD_RELOAD

    dnl multi dimensional set with intervals (3 dimensions)
    FWD_CHECK([--permanent --new-ipset=foobar --type=hash:ip,port,net], 0, ignore)
    FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.10,sctp:1234,10.10.10.0/24], 0, ignore)
    FWD_RELOAD
    FWD_CHECK([--ipset=foobar --add-entry=1.2.3.4,tcp:8080,1.6.0.0/16], 0, ignore)
    NFT_LIST_SET([foobar], 0, [dnl
        table inet firewalld {
            set foobar {
                type ipv4_addr . inet_proto . inet_service . ipv4_addr
                flags interval
                elements = { 10.10.10.10 . sctp . 1234 . 10.10.10.0/24,
                             1.2.3.4 . tcp . 8080 . 1.6.0.0/16 }
            }
        }
    ])
    IPSET_LIST_SET([foobar], 0, [dnl
        Name: foobar
        Type: hash:ip,port,net
        Members:
        1.2.3.4,tcp:8080,1.6.0.0/16
        10.10.10.10,sctp:1234,10.10.10.0/24
    ])
    FWD_CHECK([--permanent --delete-ipset=foobar], 0, ignore)
    FWD_RELOAD

    dnl hash:net,iface
    FWD_CHECK([--permanent --new-ipset=foobar --type=hash:net,iface], 0, ignore)
    FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.0/24,foobar0], 0, ignore)
    FWD_RELOAD
    FWD_CHECK([--ipset=foobar --add-entry=20.20.20.0/24,raboof0], 0, ignore)
    FWD_CHECK([--zone internal --add-source=ipset:foobar], 0, ignore)
    NFT_LIST_SET([foobar], 0, [dnl
        table inet firewalld {
            set foobar {
                type ipv4_addr . ifname
                flags interval
                elements = { 10.10.10.0/24 . "foobar0",
                             20.20.20.0/24 . "raboof0" }
            }
        }
    ])
    NFT_LIST_RULES([inet], [filter_INPUT_ZONES], 0, [dnl
        table inet firewalld {
            chain filter_INPUT_ZONES {
                ip saddr . oifname @foobar goto filter_IN_internal
                goto filter_IN_public
            }
        }
    ])
    IPSET_LIST_SET([foobar], 0, [dnl
        Name: foobar
        Type: hash:net,iface
        Members:
        10.10.10.0/24,foobar0
        20.20.20.0/24,raboof0
    ])
    FWD_CHECK([--permanent --delete-ipset=foobar], 0, ignore)
    FWD_RELOAD

    IF_HOST_SUPPORTS_IPV6_RULES([
    FWD_CHECK([--permanent --new-ipset=foobar --type=hash:mac], 0, ignore)
    FWD_CHECK([--permanent --ipset=foobar --add-entry=12:34:56:78:90:ab], 0, ignore)
    FWD_RELOAD
    FWD_CHECK([--ipset=foobar --add-entry=12:34:56:78:90:ac], 0, ignore)
    FWD_CHECK([--permanent --delete-ipset=foobar], 0, ignore)
    FWD_RELOAD
    ])
FWD_END_TEST([-e '/ERROR: INVALID_ENTRY: invalid address/d'])

FWD_START_TEST([user helpers])
    AT_KEYWORDS(helper)

    FWD_CHECK([--permanent --new-helper=foobar --module=foo], 132, ignore, ignore)
    FWD_CHECK([--permanent --new-helper=foobar --module=nf_conntrack_foo], 0, ignore)
    FWD_CHECK([--permanent --get-helpers | grep foobar], 0, ignore)
    FWD_CHECK([--permanent --helper=foobar --get-family | grep ipv4], 1, ignore)
    FWD_CHECK([--permanent --helper=foobar --set-family=ipv5], 111, ignore, ignore)
    FWD_CHECK([--permanent --helper=foobar --set-family=ipv4], 0, ignore)
    FWD_CHECK([--permanent --helper=foobar --get-family | grep ipv4], 0, ignore)
    FWD_CHECK([--permanent --helper=foobar --set-family=], 0, ignore)

    FWD_CHECK([--permanent --helper=foobar --get-family], 0, [
])
    FWD_CHECK([--permanent --helper=foobar --get-ports], 0, [
])

    FWD_CHECK([--permanent --helper=foobar --add-port=44/tcp], 0, ignore)
    FWD_CHECK([--permanent --helper=foobar --get-ports | grep 44], 0, ignore)
    FWD_CHECK([--permanent --helper=foobar --query-port=44/tcp], 0, ignore)
    FWD_CHECK([--permanent --helper=foobar --remove-port=44/tcp], 0, ignore)
    FWD_CHECK([--permanent --helper=foobar --query-port=44/tcp], 1, ignore)
    FWD_CHECK([--permanent --helper=foobar --get-ports], 0, [
])
    FWD_CHECK([--permanent --delete-helper=foobar], 0, ignore)
    FWD_CHECK([--permanent --get-helpers | grep foobar], 1, ignore)
FWD_END_TEST([-e '/ERROR: INVALID_MODULE:/d'])

FWD_START_TEST([direct])
    AT_KEYWORDS(direct)

    FWD_CHECK([--direct --add-chain ipv4 filter mychain], 0, ignore)
    FWD_CHECK([--direct --get-chains ipv4 filter | grep mychain], 0, ignore)
    FWD_CHECK([--direct --get-all-chains | grep "ipv4 filter mychain"], 0, ignore)
    FWD_CHECK([--direct --query-chain ipv4 filter mychain], 0, ignore)
    FWD_CHECK([--direct --add-chain ipv5 filter mychain], 111, ignore, ignore)
    FWD_CHECK([--direct --add-chain ipv4 badtable mychain], 108, ignore, ignore)

    FWD_CHECK([--direct --add-rule ipv4 filter mychain 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --get-rules ipv4 filter mychain | grep "3 -j ACCEPT"], 0, ignore)
    FWD_CHECK([--direct --get-all-rules | grep "ipv4 filter mychain 3 -j ACCEPT"], 0, ignore)
    FWD_CHECK([--direct --query-rule ipv4 filter mychain 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --remove-rule ipv4 filter mychain 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --query-rule ipv4 filter mychain 3 -j ACCEPT], 1, ignore)
    FWD_CHECK([--direct --add-rule ipv5 filter mychain 3 -j ACCEPT], 111, ignore, ignore)
    FWD_CHECK([--direct --add-rule ipv4 badtable mychain 3 -j ACCEPT], 108, ignore, ignore)

    FWD_CHECK([--direct --add-rule ipv4 filter mychain 3 -s 192.168.1.1 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --add-rule ipv4 filter mychain 4 -s 192.168.1.2 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --add-rule ipv4 filter mychain 5 -s 192.168.1.3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --add-rule ipv4 filter mychain 6 -s 192.168.1.4 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --get-rules ipv4 filter mychain | grep "3 -s 192.168.1.1 -j ACCEPT"], 0, ignore)
    FWD_CHECK([--direct --get-rules ipv4 filter mychain | grep "4 -s 192.168.1.2 -j ACCEPT"], 0, ignore)
    FWD_CHECK([--direct --get-rules ipv4 filter mychain | grep "5 -s 192.168.1.3 -j ACCEPT"], 0, ignore)
    FWD_CHECK([--direct --get-rules ipv4 filter mychain | grep "6 -s 192.168.1.4 -j ACCEPT"], 0, ignore)
    FWD_CHECK([--direct --remove-rules ipv4 filter mychain], 0, ignore)
    FWD_CHECK([--direct --query-rule ipv4 filter mychain 3 -s 192.168.1.1 -j ACCEPT], 1, ignore)
    FWD_CHECK([--direct --query-rule ipv4 filter mychain 4 -s 192.168.1.2 -j ACCEPT], 1, ignore)
    FWD_CHECK([--direct --query-rule ipv4 filter mychain 5 -s 192.168.1.3 -j ACCEPT], 1, ignore)
    FWD_CHECK([--direct --query-rule ipv4 filter mychain 6 -s 192.168.1.4 -j ACCEPT], 1, ignore)

    FWD_CHECK([--direct --remove-chain ipv5 filter mychain], 111, ignore, ignore)
    FWD_CHECK([--direct --remove-chain ipv4 badtable mychain], 108, ignore, ignore)
    FWD_CHECK([--direct --remove-chain ipv4 filter mychain], 0, ignore)
    FWD_CHECK([--direct --query-chain ipv4 filter mychain], 1, ignore)
    FWD_CHECK([--direct --remove-chain ipv4 filter dummy], 0, ignore, ignore)

    dnl impossible combinations
    FWD_CHECK([--direct --reload], 2, ignore, ignore)
    FWD_CHECK([--direct --list-all], 2, ignore, ignore)
    FWD_CHECK([--direct --get-services], 2, ignore, ignore)
    FWD_CHECK([--direct --get-default-zone], 2, ignore, ignore)
    FWD_CHECK([--direct --zone=home --list-services], 2, ignore, ignore)
    FWD_CHECK([--direct --permanent --list-all], 2, ignore, ignore)

    dnl try some non-ascii magic
    FWD_CHECK([--permanent --direct --add-chain ipv4 filter žluťoučký], 0, ignore)
    FWD_CHECK([--permanent --direct --get-chains ipv4 filter |grep "žluťoučký"], 0, ignore)
    FWD_CHECK([--permanent --direct --get-all-chains | grep "ipv4 filter žluťoučký"], 0, ignore)
    FWD_CHECK([--permanent --direct --query-chain ipv4 filter žluťoučký], 0, ignore)
    FWD_CHECK([--permanent --direct --add-rule ipv4 filter žluťoučký 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--permanent --direct --get-rules ipv4 filter žluťoučký | grep ACCEPT], 0, ignore)
    FWD_CHECK([--permanent --direct --get-all-rules | grep "ipv4 filter žluťoučký 3 -j ACCEPT"], 0, ignore)
    FWD_CHECK([--permanent --direct --query-rule ipv4 filter žluťoučký 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--permanent --direct --remove-rule ipv4 filter žluťoučký 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--permanent --direct --query-rule ipv4 filter žluťoučký 3 -j ACCEPT], 1, ignore)
    FWD_CHECK([--permanent --direct --remove-chain ipv4 filter žluťoučký], 0, ignore)
    FWD_CHECK([--permanent --direct --query-chain ipv4 filter žluťoučký], 1, ignore)

    dnl rhbz 1614048 - add rule to chain with _direct suffix
    FWD_CHECK([--direct --add-rule ipv4 filter INPUT_direct 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --add-rule ipv4 filter FORWARD_direct 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --add-rule ipv4 security INPUT_direct 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --add-rule ipv4 raw PREROUTING_direct 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --add-rule ipv4 mangle PREROUTING_direct 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--direct --add-rule ipv4 nat PREROUTING_direct 3 -j ACCEPT], 0, ignore)
    FWD_CHECK([--permanent --direct --add-rule ipv4 filter INPUT_direct 3 -j ACCEPT], 0, ignore)
    FWD_RELOAD
FWD_END_TEST([-e '/ERROR: INVALID_TABLE:/d' dnl
              -e '/WARNING: NOT_ENABLED: chain/d'])

FWD_START_TEST([direct nat])
    AT_KEYWORDS(direct nat)

    CHECK_NAT_COEXISTENCE

    m4_define([direct_rule1], [ipv4 nat OUTPUT 0 -s 1.2.3.4 -d 1.2.3.4 -p tcp --dport 80 -j REDIRECT --to-ports 81])
    m4_define([direct_rule2], [ipv4 nat OUTPUT 0 -s 1.2.3.4 -d 1.2.3.4 -p tcp --dport 80 -j REDIRECT --to-ports 82])
    FWD_CHECK([--permanent --direct --add-rule direct_rule1], 0, ignore)
    FWD_CHECK([--permanent --direct --get-all-rules | grep "direct_rule1"], 0, ignore)
    FWD_CHECK([--reload], 0, ignore)
    FWD_CHECK([--direct --get-all-rules | grep "direct_rule1"], 0, ignore)
    FWD_CHECK([--permanent --direct --remove-rule direct_rule1], 0, ignore)
    FWD_CHECK([--permanent --direct --add-rule direct_rule2], 0, ignore)
    FWD_CHECK([--permanent --direct --get-all-rules | grep "direct_rule2"], 0, ignore)
    FWD_CHECK([--reload], 0, ignore)
    FWD_CHECK([--direct --get-all-rules |grep "direct_rule1"], 1, ignore)
    FWD_CHECK([--direct --get-all-rules | grep "direct_rule2"], 0, ignore)
    FWD_CHECK([--permanent --direct --remove-rule direct_rule2], 0, ignore)
    FWD_CHECK([--reload], 0, ignore)
    FWD_CHECK([--direct --get-all-rules | grep "direct_rule2"], 1, ignore)
    m4_undefine([direct_rule1])
    m4_undefine([direct_rule2])
FWD_END_TEST

FWD_START_TEST([direct passthrough])
    AT_KEYWORDS(direct passthrough)

    FWD_CHECK([--direct --passthrough ipv4 --table mangle --append POSTROUTING --out-interface dummy0 --protocol udp --destination-port 68 --jump CHECKSUM --checksum-fill], 0, ignore)
    FWD_CHECK([--direct --passthrough ipv4 --table mangle --delete POSTROUTING --out-interface dummy0 --protocol udp --destination-port 68 --jump CHECKSUM --checksum-fill], 0, ignore)

    FWD_CHECK([--direct --add-passthrough ipv7 --table filter -A INPUT --in-interface dummy0 --protocol tcp --destination-port 67 --jump ACCEPT], 111, ignore, ignore)
    FWD_CHECK([--direct --add-passthrough ipv4 --table filter --append INPUT --in-interface dummy0 --protocol tcp --destination-port 67 --jump ACCEPT], 0, ignore)
    FWD_CHECK([--direct --query-passthrough ipv7 --table filter -A INPUT --in-interface dummy0 --protocol tcp --destination-port 67 --jump ACCEPT], 111, ignore, ignore)
    FWD_CHECK([--direct --query-passthrough ipv4 --table filter --append INPUT --in-interface dummy0 --protocol tcp --destination-port 67 --jump ACCEPT], 0, ignore)
    FWD_CHECK([--direct --remove-passthrough ipv7 --table filter -A INPUT --in-interface dummy0 --protocol tcp --destination-port 67 --jump ACCEPT], 111, ignore, ignore)
    FWD_CHECK([--direct --remove-passthrough ipv4 --table filter --append INPUT --in-interface dummy0 --protocol tcp --destination-port 67 --jump ACCEPT], 0, ignore)
    FWD_CHECK([--direct --query-passthrough ipv4 --table filter --append INPUT --in-interface dummy0 --protocol tcp --destination-port 67 --jump ACCEPT], 1, ignore, ignore)

    IF_HOST_SUPPORTS_IP6TABLES([
    FWD_CHECK([--direct --add-passthrough ipv6 --table filter --append FORWARD --destination fd00:dead:beef:ff0::/64 --in-interface dummy0 --out-interface dummy0 --jump ACCEPT], 0, ignore)
    FWD_CHECK([--direct --get-passthroughs ipv6 | grep "fd00:dead:beef:ff0::/64"], 0, ignore)
    FWD_CHECK([--direct --get-all-passthroughs | grep "fd00:dead:beef:ff0::/64"], 0, ignore)
    FWD_CHECK([--direct --passthrough ipv6 -nvL | grep "fd00:dead:beef:ff0::/64"], 0, ignore)
    FWD_CHECK([--direct --remove-passthrough ipv6 --table filter --delete FORWARD --destination fd00:dead:beef:ff0::/64 --in-interface dummy0 --out-interface dummy0 --jump ACCEPT], 0, ignore, ignore)
    ])

    FWD_CHECK([--direct --passthrough ipv5 -nvL], 111, ignore, ignore)
    FWD_CHECK([--direct --passthrough ipv4], 2, ignore, ignore)

    FWD_CHECK([--direct --passthrough --get-chains ipv4 filter], 111, ignore, ignore)

    FWD_CHECK([--permanent --direct --add-passthrough ipv4], 2, ignore, ignore)
    FWD_CHECK([--permanent --direct --add-passthrough ipv5 -nvL], 111, ignore, ignore)
    FWD_CHECK([--permanent --direct --add-passthrough ipv4 -nvL], 0, ignore)
    FWD_CHECK([--permanent --direct --get-passthroughs ipv4 | grep "\-nvL"], 0, ignore)
    FWD_CHECK([--permanent --direct --get-all-passthroughs | grep "ipv4 \-nvL"], 0, ignore)
    FWD_CHECK([--permanent --direct --query-passthrough ipv4 -nvL], 0, ignore)
    FWD_CHECK([--permanent --direct --remove-passthrough ipv4 -nvL], 0, ignore)
    FWD_CHECK([--permanent --direct --query-passthrough ipv4 -nvL], 1, ignore, ignore)
FWD_END_TEST([-e '/WARNING: NOT_ENABLED: passthrough/d'])

FWD_START_TEST([direct ebtables])
    AT_KEYWORDS(direct ebtables)

    FWD_CHECK([--direct --add-chain eb filter mychain], 0, ignore)
    FWD_CHECK([--direct --get-chains eb filter | grep mychain], 0, ignore)
    FWD_CHECK([--direct --add-rule eb filter mychain 1 -p 0x86dd -j DROP], 0, ignore)
    FWD_CHECK([--direct --add-rule eb filter mychain 999 -p IPv6 --ip6-protocol UDP --ip6-source-port ! 12345 -j DROP], 0, ignore)
    EBTABLES_LIST_RULES([filter], [mychain], 0, [dnl
        -p IPv6 -j DROP
        -p IPv6 --ip6-proto udp ! --ip6-sport 12345 -j DROP
        -j RETURN
    ])
    FWD_CHECK([--direct --remove-rule eb filter mychain 1 -p 0x86dd -j DROP], 0, ignore)
    EBTABLES_LIST_RULES([filter], [mychain], 0, [dnl
        -p IPv6 --ip6-proto udp ! --ip6-sport 12345 -j DROP
        -j RETURN
    ])

    FWD_CHECK([--direct --add-rule eb filter INPUT 1 -p 0x86dd -j DROP], 0, ignore)
    FWD_CHECK([--direct --add-rule eb filter INPUT_direct 1 -p 0x86dd -j DROP], 0, ignore)
    m4_if(nftables, FIREWALL_BACKEND, [dnl
        EBTABLES_LIST_RULES([filter], [INPUT], 0, [dnl
            -p IPv6 -j DROP
            -p IPv6 -j DROP
        ])], [dnl
        EBTABLES_LIST_RULES([filter], [INPUT_direct], 0, [dnl
            -p IPv6 -j DROP
            -p IPv6 -j DROP
            -j RETURN
        ])
    ])

    FWD_CHECK([--direct --remove-rules eb filter INPUT], 0, ignore)
    FWD_CHECK([--direct --remove-rules eb filter mychain], 0, ignore)

    FWD_CHECK([--permanent --direct --add-chain eb filter mychain], 0, ignore)
    FWD_CHECK([--permanent --direct --get-chains eb filter | grep mychain], 0, ignore)
    FWD_CHECK([--permanent --direct --add-rule eb filter mychain 1 -p 0x86dd -j DROP], 0, ignore)
    FWD_RELOAD
    EBTABLES_LIST_RULES([filter], [mychain], 0, [dnl
        -p IPv6 -j DROP
        -j RETURN
    ])
FWD_END_TEST

FWD_START_TEST([lockdown])
    AT_KEYWORDS(lockdown)

    FWD_CHECK([--add-lockdown-whitelist-command /usr/bin/command], 0, ignore)
    FWD_CHECK([--query-lockdown-whitelist-command /usr/bin/command], 0, ignore)
    FWD_CHECK([--list-lockdown-whitelist-commands | grep "/usr/bin/command"], 0, ignore)
    FWD_CHECK([--remove-lockdown-whitelist-command /usr/bin/command], 0, ignore)
    FWD_CHECK([--query-lockdown-whitelist-command /usr/bin/command], 1, ignore)
    FWD_CHECK([--permanent --add-lockdown-whitelist-command /usr/bin/command], 0, ignore)
    FWD_CHECK([--permanent --query-lockdown-whitelist-command /usr/bin/command], 0, ignore)
    FWD_CHECK([--permanent --list-lockdown-whitelist-commands | grep "/usr/bin/command"], 0, ignore)
    FWD_CHECK([--permanent --remove-lockdown-whitelist-command /usr/bin/command], 0, ignore)
    FWD_CHECK([--permanent --query-lockdown-whitelist-command /usr/bin/command], 1, ignore)

    FWD_CHECK([--add-lockdown-whitelist-context system_u:system_r:MadDaemon_t:s0], 0, ignore)
    FWD_CHECK([--query-lockdown-whitelist-context system_u:system_r:MadDaemon_t:s0], 0, ignore)
    FWD_CHECK([--list-lockdown-whitelist-contexts | grep "system_u:system_r:MadDaemon_t:s0"], 0, ignore)
    FWD_CHECK([--remove-lockdown-whitelist-context system_u:system_r:MadDaemon_t:s0], 0, ignore)
    FWD_CHECK([--query-lockdown-whitelist-context system_u:system_r:MadDaemon_t:s0], 1, ignore)
    FWD_CHECK([--permanent --add-lockdown-whitelist-context system_u:system_r:MadDaemon_t:s0], 0, ignore)
    FWD_CHECK([--permanent --query-lockdown-whitelist-context system_u:system_r:MadDaemon_t:s0], 0, ignore)
    FWD_CHECK([--permanent --list-lockdown-whitelist-contexts | grep "system_u:system_r:MadDaemon_t:s0"], 0, ignore)
    FWD_CHECK([--permanent --remove-lockdown-whitelist-context system_u:system_r:MadDaemon_t:s0], 0, ignore)
    FWD_CHECK([--permanent --query-lockdown-whitelist-context system_u:system_r:MadDaemon_t:s0], 1, ignore)

    FWD_CHECK([--add-lockdown-whitelist-uid 6666], 0, ignore)
    FWD_CHECK([--query-lockdown-whitelist-uid 6666], 0, ignore)
    FWD_CHECK([--list-lockdown-whitelist-uids | grep "6666"], 0, ignore)
    FWD_CHECK([--remove-lockdown-whitelist-uid 6666], 0, ignore)
    FWD_CHECK([--query-lockdown-whitelist-uid 6666], 1, ignore)
    FWD_CHECK([--add-lockdown-whitelist-uid 6666x], 2, ignore, ignore)
    FWD_CHECK([--permanent --add-lockdown-whitelist-uid 6666], 0, ignore)
    FWD_CHECK([--permanent --query-lockdown-whitelist-uid 6666], 0, ignore)
    FWD_CHECK([--permanent --list-lockdown-whitelist-uids | grep "6666"], 0, ignore)
    FWD_CHECK([--permanent --remove-lockdown-whitelist-uid 6666], 0, ignore)
    FWD_CHECK([--permanent --query-lockdown-whitelist-uid 6666], 1, ignore)
    FWD_CHECK([--permanent --add-lockdown-whitelist-uid 6666x], 2, ignore, ignore)

    FWD_CHECK([--add-lockdown-whitelist-user theboss], 0, ignore)
    FWD_CHECK([--query-lockdown-whitelist-user theboss], 0, ignore)
    FWD_CHECK([--list-lockdown-whitelist-users | grep "theboss"], 0, ignore)
    FWD_CHECK([--remove-lockdown-whitelist-user theboss], 0, ignore)
    FWD_CHECK([--query-lockdown-whitelist-user theboss], 1, ignore)
    FWD_CHECK([--permanent --add-lockdown-whitelist-user theboss], 0, ignore)
    FWD_CHECK([--permanent --query-lockdown-whitelist-user theboss], 0, ignore)
    FWD_CHECK([--permanent --list-lockdown-whitelist-users | grep "theboss"], 0, ignore)
    FWD_CHECK([--permanent --remove-lockdown-whitelist-user theboss], 0, ignore)
    FWD_CHECK([--permanent --query-lockdown-whitelist-user theboss], 1, ignore)

    AT_SKIP_IF([test `whoami` != 'root'])
    FWD_CHECK([--add-lockdown-whitelist-user root], 0, ignore)
    FWD_CHECK([--lockdown-on], 0, ignore)
    FWD_CHECK([--query-lockdown], 0, ignore)
    FWD_CHECK([--lockdown-off], 0, ignore)
    FWD_CHECK([--query-lockdown], 1, ignore)
FWD_END_TEST

m4_define([rich_rule_test], [
    FWD_CHECK([--add-rich-rule='$1'], 0, ignore)
    FWD_CHECK([--query-rich-rule='$1'], 0, ignore)
    FWD_CHECK([--remove-rich-rule='$1'], 0, ignore)
    FWD_CHECK([--query-rich-rule='$1'], 1, ignore)
    FWD_CHECK([--permanent --add-rich-rule='$1'], 0, ignore)
    FWD_CHECK([--permanent --query-rich-rule='$1'], 0, ignore)
    FWD_CHECK([--permanent --remove-rich-rule='$1'], 0, ignore)
    FWD_CHECK([--permanent --query-rich-rule='$1'], 1, ignore)
])
FWD_START_TEST([rich rules good])
    AT_KEYWORDS(rich)

    rich_rule_test([rule protocol value="ah" reject])
    rich_rule_test([rule protocol value="esp" accept])
    rich_rule_test([rule protocol value="sctp" log])
    rich_rule_test([rule family="ipv4" source address="192.168.0.0/24" service name="tftp" log prefix="tftp: " level="info" limit value="1/m" accept])
    rich_rule_test([rule family="ipv4" source not address="192.168.0.0/24" service name="dns" log prefix="dns: " level="info" limit value="2/m" drop])
    IF_HOST_SUPPORTS_IPV6_RULES([
    rich_rule_test([rule family="ipv6" source address="1:2:3:4:6::" service name="radius" log prefix="dns -- " level="info" limit value="3/m" reject type="icmp6-addr-unreachable" limit value="20/m"])
    rich_rule_test([rule family="ipv6" source address="1:2:3:4:6::" port port="4011" protocol="tcp" log prefix="port 4011: " level="info" limit value="4/m" drop])
    rich_rule_test([rule family="ipv6" source address="1:2:3:4:6::" forward-port port="4011" protocol="tcp" to-port="4012" to-addr="1::2:3:4:7"])
    rich_rule_test([rule family="ipv6" source address="1:2:3:4:6::" icmp-block name="redirect" log prefix="redirected: " level="info" limit value="4/m"])
    rich_rule_test([rule family="ipv6" source address="1:2:3:4::/64" destination address="1:2:3:5::/64" accept])
    rich_rule_test([rule family="ipv6" masquerade])
    ])
    rich_rule_test([rule family="ipv4" destination address="1.2.3.4" forward-port port="4011" protocol="tcp" to-port="4012" to-addr="9.8.7.6"])
    rich_rule_test([rule family="ipv4" source address="192.168.0.0/24" icmp-block name="source-quench" log prefix="source-quench: " level="info" limit value="4/m"])
    rich_rule_test([rule family="ipv4" source address="192.168.1.0/24" masquerade])
    rich_rule_test([rule family="ipv4" source address="10.1.1.0/24" destination address="192.168.1.0/24" accept])
    rich_rule_test([rule family="ipv4" destination address="192.168.1.0/24" masquerade])
    rich_rule_test([rule forward-port port="2222" to-port="22" to-addr="192.168.100.2" protocol="tcp" family="ipv4" source address="192.168.2.100"])
    rich_rule_test([rule forward-port port="66" to-port="666" to-addr="192.168.100.2" protocol="sctp" family="ipv4" source address="192.168.2.100"])
    IF_HOST_SUPPORTS_IPV6_RULES([
    rich_rule_test([rule forward-port port="99" to-port="999" to-addr="1::2:3:4:7" protocol="dccp" family="ipv6" source address="1:2:3:4:6::"])
    rich_rule_test([rule forward-port port="99" to-port="10999" to-addr="1::2:3:4:7" protocol="dccp" family="ipv6" source address="1:2:3:4:6::"])
    ])
    rich_rule_test([rule family="ipv4" port port="222" protocol="tcp" mark set="0xff"])
FWD_END_TEST([-e '/ERROR: Failed to write to file .*\/proc\/sys\/net\/ipv6\/conf\/all\/forwarding.*/d'])
FWD_START_TEST([rich rules audit])
    AT_KEYWORDS(rich)

    CHECK_LOG_AUDIT
    rich_rule_test([rule service name="ftp" audit limit value="1/m" accept])
FWD_END_TEST
m4_undefine([rich_rule_test])

FWD_START_TEST([rich rules priority])
    AT_KEYWORDS(rich)

    CHECK_LOG_AUDIT

    dnl Expected test results assume this is set to "no"
    AT_CHECK([sed -i 's/^AllowZoneDrifting.*/AllowZoneDrifting=no/' ./firewalld.conf])
    FWD_RELOAD

    dnl Verify generic layout of zone
    NFT_LIST_RULES([inet], [filter_IN_public], 0, [dnl
        table inet firewalld {
        chain filter_IN_public {
        jump filter_IN_public_pre
        jump filter_IN_public_log
        jump filter_IN_public_deny
        jump filter_IN_public_allow
        jump filter_IN_public_post
        meta l4proto { icmp, ipv6-icmp } accept
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_FWDI_public], 0, [dnl
        table inet firewalld {
        chain filter_FWDI_public {
        jump filter_FWDI_public_pre
        jump filter_FWDI_public_log
        jump filter_FWDI_public_deny
        jump filter_FWDI_public_allow
        jump filter_FWDI_public_post
        meta l4proto { icmp, ipv6-icmp } accept
        }
        }
    ])
    IPTABLES_LIST_RULES([filter], [IN_public], 0, [dnl
        IN_public_pre all -- 0.0.0.0/0 0.0.0.0/0
        IN_public_log all -- 0.0.0.0/0 0.0.0.0/0
        IN_public_deny all -- 0.0.0.0/0 0.0.0.0/0
        IN_public_allow all -- 0.0.0.0/0 0.0.0.0/0
        IN_public_post all -- 0.0.0.0/0 0.0.0.0/0
        ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
    ])
    IPTABLES_LIST_RULES([filter], [FWDI_public], 0, [dnl
        FWDI_public_pre all -- 0.0.0.0/0 0.0.0.0/0
        FWDI_public_log all -- 0.0.0.0/0 0.0.0.0/0
        FWDI_public_deny all -- 0.0.0.0/0 0.0.0.0/0
        FWDI_public_allow all -- 0.0.0.0/0 0.0.0.0/0
        FWDI_public_post all -- 0.0.0.0/0 0.0.0.0/0
        ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public], 0, [dnl
        IN_public_pre all ::/0 ::/0
        IN_public_log all ::/0 ::/0
        IN_public_deny all ::/0 ::/0
        IN_public_allow all ::/0 ::/0
        IN_public_post all ::/0 ::/0
        ACCEPT icmpv6 ::/0 ::/0
    ])
    IP6TABLES_LIST_RULES([filter], [FWDI_public], 0, [dnl
        FWDI_public_pre all ::/0 ::/0
        FWDI_public_log all ::/0 ::/0
        FWDI_public_deny all ::/0 ::/0
        FWDI_public_allow all ::/0 ::/0
        FWDI_public_post all ::/0 ::/0
        ACCEPT icmpv6 ::/0 ::/0
    ])

    dnl priority 0 (or not specified) is special:
    dnl     accept goes to _allow chain
    dnl     drop   goes to _deny chain
    dnl     log    goes to _log chain
    dnl     audit  goes to _log chain
    FWD_CHECK([--add-rich-rule='rule port port="1111" protocol="tcp" log'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=0 port port="1122" protocol="tcp" audit accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule port port="2222" protocol="tcp" drop'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule port port="3333" protocol="tcp" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=0 port port="4444" protocol="tcp" accept'], 0, ignore)
    NFT_LIST_RULES([inet], [filter_IN_public_log], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_log {
        tcp dport 1111 ct state new,untracked log
        tcp dport 1122 ct state new,untracked log level audit
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_deny], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_deny {
        tcp dport 2222 ct state new,untracked drop
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_allow], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_allow {
        tcp dport 22 ct state new,untracked accept
        ip6 daddr fe80::/64 udp dport 546 ct state new,untracked accept
        tcp dport 9090 ct state new,untracked accept
        tcp dport 1122 ct state new,untracked accept
        tcp dport 3333 ct state new,untracked accept
        tcp dport 4444 ct state new,untracked accept
        }
        }
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_log], 0, [dnl
        LOG tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:1111 ctstate NEW,UNTRACKED LOG flags 0 level 4
        AUDIT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:1122 ctstate NEW,UNTRACKED AUDIT accept
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_deny], 0, [dnl
        DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:2222 ctstate NEW,UNTRACKED
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_allow], 0, [dnl
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9090 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:1122 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:3333 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:4444 ctstate NEW,UNTRACKED
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_log], 0, [dnl
        LOG tcp ::/0 ::/0 tcp dpt:1111 ctstate NEW,UNTRACKED LOG flags 0 level 4
        AUDIT tcp ::/0 ::/0 tcp dpt:1122 ctstate NEW,UNTRACKED AUDIT accept
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_deny], 0, [dnl
        DROP tcp ::/0 ::/0 tcp dpt:2222 ctstate NEW,UNTRACKED
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_allow], 0, [dnl
        ACCEPT tcp ::/0 ::/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT udp ::/0 fe80::/64 udp dpt:546 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:9090 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:1122 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:3333 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:4444 ctstate NEW,UNTRACKED
    ])
    FWD_RELOAD

    dnl verify priority range
    FWD_CHECK([--add-rich-rule='rule priority=-32768 port port="1234" protocol="tcp" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=32767 port port="1234" protocol="tcp" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=-32769 port port="1234" protocol="tcp" accept'], 139, ignore, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=32768 port port="1234" protocol="tcp" accept'], 139, ignore, ignore)
    FWD_RELOAD

    dnl Special catch-all rule
    m4_define([rich_rule_str], ['rule priority=127 drop'])
    FWD_CHECK([--add-rich-rule=rich_rule_str], 0, ignore)
    FWD_CHECK([--query-rich-rule=rich_rule_str], 0, ignore)
    NFT_LIST_RULES([inet], [filter_IN_public_post], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_post {
        drop
        }
        }
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_post], 0, [dnl
        DROP all -- 0.0.0.0/0 0.0.0.0/0
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_post], 0, [dnl
        DROP all ::/0 ::/0
    ])
    FWD_CHECK([--remove-rich-rule=rich_rule_str], 0, ignore)
    FWD_CHECK([--query-rich-rule=rich_rule_str], 1, ignore)
    FWD_CHECK([--permanent --add-rich-rule=rich_rule_str], 0, ignore)
    FWD_CHECK([--permanent --query-rich-rule=rich_rule_str], 0, ignore)
    FWD_CHECK([--permanent --remove-rich-rule=rich_rule_str], 0, ignore)
    FWD_CHECK([--permanent --query-rich-rule=rich_rule_str], 1, ignore)
    m4_undefine([rich_rule_str])
    dnl special catch-all should be denied if priority not specified
    FWD_CHECK([--add-rich-rule='rule drop'], 122, ignore, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=0 drop'], 122, ignore, ignore)
    FWD_CHECK([--add-rich-rule='rule log prefix="foobar: "'], 122, ignore, ignore)
    FWD_RELOAD

    dnl masquerade and forward-ports are special because they use nat and mangle.
    FWD_CHECK([--add-rich-rule='rule family="ipv4" source address="10.10.0.0/16" masquerade'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=-10 source address="10.1.1.0/24" masquerade'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=-1  source address="10.1.0.0/16" drop'], 0, ignore)
    dnl
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=0 forward-port port="222"  protocol="tcp" to-port="22"'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=0 forward-port port="2222" protocol="tcp" to-port="22" to-addr="10.1.1.1"'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=-10 forward-port port="8888" protocol="tcp" to-port="80"'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=-10 forward-port port="8080" protocol="tcp" to-port="80" to-addr="10.1.1.1"'], 0, ignore)
    IF_HOST_SUPPORTS_IPV6_RULES([
    FWD_CHECK([--add-rich-rule='rule family="ipv6" priority=0 forward-port port="9090" protocol="tcp" to-port="90"'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv6" priority=-123 forward-port port="999" protocol="tcp" to-port="99"'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv6" priority=-123 forward-port port="9999" protocol="tcp" to-port="9999" to-addr="1234::4321"'], 0, ignore)
    ])
    NFT_LIST_RULES([inet], [filter_INPUT], 0, [dnl
        table inet firewalld {
        chain filter_INPUT {
        ct state established,related accept
        ct status dnat accept
        iifname "lo" accept
        jump filter_INPUT_ZONES
        ct state invalid drop
        reject with icmpx type admin-prohibited
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_pre], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_pre {
        ip saddr 10.1.0.0/16 drop
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_allow], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_allow {
        tcp dport 22 ct state new,untracked accept
        ip6 daddr fe80::/64 udp dport 546 ct state new,untracked accept
        tcp dport 9090 ct state new,untracked accept
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_FWDI_public_pre], 0, [dnl
        table inet firewalld {
        chain filter_FWDI_public_pre {
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_FWDI_public_allow], 0, [dnl
        table inet firewalld {
        chain filter_FWDI_public_allow {
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_FWDO_public_pre], 0, [dnl
        table inet firewalld {
        chain filter_FWDO_public_pre {
        ip saddr 10.1.1.0/24 ct state new,untracked accept
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_FWDO_public_allow], 0, [dnl
        table inet firewalld {
        chain filter_FWDO_public_allow {
        ip saddr 10.10.0.0/16 ct state new,untracked accept
        }
        }
    ])
    NFT_LIST_RULES([ip], [nat_PRE_public_pre], 0, [dnl
        table ip firewalld {
        chain nat_PRE_public_pre {
        tcp dport 8888 redirect to :80
        tcp dport 8080 dnat to 10.1.1.1:80
        }
        }
    ])
    NFT_LIST_RULES([ip], [nat_PRE_public_allow], 0, [dnl
        table ip firewalld {
        chain nat_PRE_public_allow {
        tcp dport 222 redirect to :22
        tcp dport 2222 dnat to 10.1.1.1:22
        }
        }
    ])
    NFT_LIST_RULES([ip], [nat_POST_public_pre], 0, [dnl
        table ip firewalld {
        chain nat_POST_public_pre {
        ip saddr 10.1.1.0/24 oifname != "lo" masquerade
        }
        }
    ])
    NFT_LIST_RULES([ip], [nat_POST_public_allow], 0, [dnl
        table ip firewalld {
        chain nat_POST_public_allow {
        ip saddr 10.10.0.0/16 oifname != "lo" masquerade
        }
        }
    ])
    NFT_LIST_RULES([ip6], [nat_PRE_public_pre], 0,
        [[table ip6 firewalld {
        chain nat_PRE_public_pre {
        tcp dport 999 redirect to :99
        tcp dport 9999 dnat to [1234::4321]:9999
        }
        }
    ]])
    NFT_LIST_RULES([ip6], [nat_PRE_public_allow], 0, [dnl
        table ip6 firewalld {
        chain nat_PRE_public_allow {
        tcp dport 9090 redirect to :90
        }
        }
    ])
    NFT_LIST_RULES([ip6], [nat_POST_public_pre], 0, [dnl
        table ip6 firewalld {
        chain nat_POST_public_pre {
        }
        }
    ])
    NFT_LIST_RULES([ip6], [nat_POST_public_allow], 0, [dnl
        table ip6 firewalld {
        chain nat_POST_public_allow {
        }
        }
    ])
    NFT_LIST_RULES([inet], [mangle_PRE_public_pre], 0, [dnl
        table inet firewalld {
        chain mangle_PRE_public_pre {
        }
        }
    ])
    NFT_LIST_RULES([inet], [mangle_PRE_public_allow], 0, [dnl
        table inet firewalld {
        chain mangle_PRE_public_allow {
        }
        }
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_pre], 0, [dnl
        DROP all -- 10.1.0.0/16 0.0.0.0/0
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_allow], 0, [dnl
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9090 ctstate NEW,UNTRACKED
    ])
    IPTABLES_LIST_RULES([filter], [FWDI_public_pre], 0, [dnl
    ])
    IPTABLES_LIST_RULES([filter], [FWDI_public_allow], 0, [dnl
    ])
    IPTABLES_LIST_RULES([filter], [FWDO_public_pre], 0, [dnl
        ACCEPT all -- 10.1.1.0/24 0.0.0.0/0 ctstate NEW,UNTRACKED
    ])
    IPTABLES_LIST_RULES([filter], [FWDO_public_allow], 0, [dnl
        ACCEPT all -- 10.10.0.0/16 0.0.0.0/0 ctstate NEW,UNTRACKED
    ])
    IPTABLES_LIST_RULES([nat], [PRE_public_pre], 0, [dnl
        DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8888 to::80
        DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:10.1.1.1:80
    ])
    IPTABLES_LIST_RULES([nat], [PRE_public_allow], 0, [dnl
        DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:222 to::22
        DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:2222 to:10.1.1.1:22
    ])
    IPTABLES_LIST_RULES([nat], [POST_public_pre], 0, [dnl
        MASQUERADE all -- 10.1.1.0/24 0.0.0.0/0
    ])
    IPTABLES_LIST_RULES([nat], [POST_public_allow], 0, [dnl
        MASQUERADE all -- 10.10.0.0/16 0.0.0.0/0
    ])
    IPTABLES_LIST_RULES([mangle], [PRE_public_pre], 0, [dnl
    ])
    IPTABLES_LIST_RULES([mangle], [PRE_public_allow], 0, [dnl
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_pre], 0, [dnl
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_allow], 0, [dnl
        ACCEPT tcp ::/0 ::/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT udp ::/0 fe80::/64 udp dpt:546 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:9090 ctstate NEW,UNTRACKED
    ])
    IP6TABLES_LIST_RULES([filter], [FWDI_public_pre], 0, [dnl
    ])
    IP6TABLES_LIST_RULES([filter], [FWDI_public_allow], 0, [dnl
    ])
    IP6TABLES_LIST_RULES([nat], [PRE_public_pre], 0,
        [[DNAT tcp ::/0 ::/0 tcp dpt:999 to::99
        DNAT tcp ::/0 ::/0 tcp dpt:9999 to:[1234::4321]:9999
    ]])
    IP6TABLES_LIST_RULES([nat], [PRE_public_allow], 0, [dnl
        DNAT tcp ::/0 ::/0 tcp dpt:9090 to::90
    ])
    IP6TABLES_LIST_RULES([mangle], [PRE_public_pre], 0, [dnl
    ])
    IP6TABLES_LIST_RULES([mangle], [PRE_public_allow], 0, [dnl
    ])
    FWD_RELOAD

    dnl icmp-block and icmp-type coverage
    FWD_CHECK([--add-rich-rule='rule icmp-block name="destination-unreachable"'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=-10 icmp-block name="destination-unreachable"'], 0, ignore)
    dnl
    FWD_CHECK([--add-rich-rule='rule icmp-type name="echo-request" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=-10 icmp-type name="echo-request" accept'], 0, ignore)
    NFT_LIST_RULES([inet], [filter_IN_public_pre], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_pre {
        icmp type destination-unreachable reject with icmpx type admin-prohibited
        icmpv6 type destination-unreachable reject with icmpx type admin-prohibited
        icmp type echo-request accept
        icmpv6 type echo-request accept
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_deny], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_deny {
        icmp type destination-unreachable reject with icmpx type admin-prohibited
        icmpv6 type destination-unreachable reject with icmpx type admin-prohibited
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_allow], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_allow {
        tcp dport 22 ct state new,untracked accept
        ip6 daddr fe80::/64 udp dport 546 ct state new,untracked accept
        tcp dport 9090 ct state new,untracked accept
        icmp type echo-request accept
        icmpv6 type echo-request accept
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_FWDI_public_pre], 0, [dnl
        table inet firewalld {
        chain filter_FWDI_public_pre {
        icmp type destination-unreachable reject with icmpx type admin-prohibited
        icmpv6 type destination-unreachable reject with icmpx type admin-prohibited
        icmp type echo-request accept
        icmpv6 type echo-request accept
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_FWDI_public_deny], 0, [dnl
        table inet firewalld {
        chain filter_FWDI_public_deny {
        icmp type destination-unreachable reject with icmpx type admin-prohibited
        icmpv6 type destination-unreachable reject with icmpx type admin-prohibited
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_FWDI_public_allow], 0, [dnl
        table inet firewalld {
        chain filter_FWDI_public_allow {
        icmp type echo-request accept
        icmpv6 type echo-request accept
        }
        }
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_pre], 0, [dnl
        REJECT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 3 reject-with icmp-host-prohibited
        ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_deny], 0, [dnl
        REJECT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 3 reject-with icmp-host-prohibited
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_allow], 0, [dnl
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9090 ctstate NEW,UNTRACKED
        ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
    ])
    IPTABLES_LIST_RULES([filter], [FWDI_public_pre], 0, [dnl
        REJECT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 3 reject-with icmp-host-prohibited
        ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
    ])
    IPTABLES_LIST_RULES([filter], [FWDI_public_deny], 0, [dnl
        REJECT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 3 reject-with icmp-host-prohibited
    ])
    IPTABLES_LIST_RULES([filter], [FWDI_public_allow], 0, [dnl
        ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_pre], 0, [dnl
        REJECT icmpv6 ::/0 ::/0 ipv6-icmptype 1 reject-with icmp6-adm-prohibited
        ACCEPT icmpv6 ::/0 ::/0 ipv6-icmptype 128
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_deny], 0, [dnl
        REJECT icmpv6 ::/0 ::/0 ipv6-icmptype 1 reject-with icmp6-adm-prohibited
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_allow], 0, [dnl
        ACCEPT tcp ::/0 ::/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT udp ::/0 fe80::/64 udp dpt:546 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:9090 ctstate NEW,UNTRACKED
        ACCEPT icmpv6 ::/0 ::/0 ipv6-icmptype 128
    ])
    IP6TABLES_LIST_RULES([filter], [FWDI_public_pre], 0, [dnl
        REJECT icmpv6 ::/0 ::/0 ipv6-icmptype 1 reject-with icmp6-adm-prohibited
        ACCEPT icmpv6 ::/0 ::/0 ipv6-icmptype 128
    ])
    IP6TABLES_LIST_RULES([filter], [FWDI_public_deny], 0, [dnl
        REJECT icmpv6 ::/0 ::/0 ipv6-icmptype 1 reject-with icmp6-adm-prohibited
    ])
    IP6TABLES_LIST_RULES([filter], [FWDI_public_allow], 0, [dnl
        ACCEPT icmpv6 ::/0 ::/0 ipv6-icmptype 128
    ])
    FWD_RELOAD

    dnl add many negative/positive priorities and make sure they're in the right order
    FWD_CHECK([--add-rich-rule='rule priority=70   service name="smtps" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=-111 service name="ntp" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=-10  port port="1111" protocol="tcp" drop'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=-100 port port="1111" protocol="tcp" log'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority="-77"    service name="smtp" accept'], 0, ignore)
    FWD_CHECK([--remove-rich-rule='rule priority=-111 service name="ntp" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=-32768 source address="10.0.0.0/8" log'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=-2 source address="10.0.0.0/8" log'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=-1 source address="10.0.0.0/8" drop'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=-5 source address="10.10.10.0/24" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule family="ipv4" priority=-3 source address="10.100.100.0/24" drop'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=127  drop'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=125 service name="imap" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=126 log prefix="DROPPED: "'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=10  service name="ssh" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=1   service name="http" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=100 service name="https" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=5   service name="https" accept'], 0, ignore)
    FWD_CHECK([--add-rich-rule='rule priority=66  service name="smtp" accept'], 0, ignore)
    FWD_CHECK([--remove-rich-rule='rule priority=66    service name="smtp" accept'], 0, ignore)
    FWD_CHECK([--remove-rich-rule='rule priority=70    service name="smtps" accept'], 0, ignore)
    FWD_CHECK([--remove-rich-rule='rule priority=5     service name="https" accept'], 0, ignore)
    FWD_CHECK([--remove-rich-rule='rule priority="-77" service name="smtp" accept'], 0, ignore)
    FWD_CHECK([--remove-rich-rule='rule family="ipv4" priority=-3 source address="10.100.100.0/24" drop'], 0, ignore)
    NFT_LIST_RULES([inet], [filter_IN_public_pre], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_pre {
        ip saddr 10.0.0.0/8 log
        tcp dport 1111 ct state new,untracked log
        tcp dport 1111 ct state new,untracked drop
        ip saddr 10.10.10.0/24 accept
        ip saddr 10.0.0.0/8 log
        ip saddr 10.0.0.0/8 drop
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_allow], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_allow {
        tcp dport 22 ct state new,untracked accept
        ip6 daddr fe80::/64 udp dport 546 ct state new,untracked accept
        tcp dport 9090 ct state new,untracked accept
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_deny], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_deny {
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_log], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_log {
        }
        }
    ])
    NFT_LIST_RULES([inet], [filter_IN_public_post], 0, [dnl
        table inet firewalld {
        chain filter_IN_public_post {
        tcp dport 80 ct state new,untracked accept
        tcp dport 22 ct state new,untracked accept
        tcp dport 443 ct state new,untracked accept
        tcp dport 143 ct state new,untracked accept
        log prefix "DROPPED: "
        drop
        }
        }
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_pre], 0, [dnl
        LOG all -- 10.0.0.0/8 0.0.0.0/0 LOG flags 0 level 4
        LOG tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:1111 ctstate NEW,UNTRACKED LOG flags 0 level 4
        DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:1111 ctstate NEW,UNTRACKED
        ACCEPT all -- 10.10.10.0/24 0.0.0.0/0
        LOG all -- 10.0.0.0/8 0.0.0.0/0 LOG flags 0 level 4
        DROP all -- 10.0.0.0/8 0.0.0.0/0
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_allow], 0, [dnl
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9090 ctstate NEW,UNTRACKED
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_deny], 0, [dnl
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_log], 0, [dnl
    ])
    IPTABLES_LIST_RULES([filter], [IN_public_post], 0, [dnl
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 ctstate NEW,UNTRACKED
        ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:143 ctstate NEW,UNTRACKED
        LOG all -- 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "'DROPPED: '"
        DROP all -- 0.0.0.0/0 0.0.0.0/0
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_pre], 0, [dnl
        LOG tcp ::/0 ::/0 tcp dpt:1111 ctstate NEW,UNTRACKED LOG flags 0 level 4
        DROP tcp ::/0 ::/0 tcp dpt:1111 ctstate NEW,UNTRACKED
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_allow], 0, [dnl
        ACCEPT tcp ::/0 ::/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT udp ::/0 fe80::/64 udp dpt:546 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:9090 ctstate NEW,UNTRACKED
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_deny], 0, [dnl
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_log], 0, [dnl
    ])
    IP6TABLES_LIST_RULES([filter], [IN_public_post], 0, [dnl
        ACCEPT tcp ::/0 ::/0 tcp dpt:80 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:22 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:443 ctstate NEW,UNTRACKED
        ACCEPT tcp ::/0 ::/0 tcp dpt:143 ctstate NEW,UNTRACKED
        LOG all ::/0 ::/0 LOG flags 0 level 4 prefix "'DROPPED: '"
        DROP all ::/0 ::/0
    ])
    FWD_CHECK([-q --runtime-to-permanent])
    FWD_RELOAD

    dnl Verify the rules are displayed in order of priority, not by when they
    dnl were added.
    FWD_CHECK([--add-rich-rule='rule priority=0 service name="http" accept'], 0, ignore)
    FWD_CHECK([--list-all | TRIM_WHITESPACE], 0, [m4_strip([dnl
        public
        target: default
        icmp-block-inversion: no
        interfaces:
        sources:
        services: cockpit dhcpv6-client ssh
        ports:
        protocols:
        masquerade: no
        forward-ports:
        source-ports:
        icmp-blocks:
        rich rules:
        rule priority="-32768" family="ipv4" source address="10.0.0.0/8" log
        rule priority="-100" port port="1111" protocol="tcp" log
        rule priority="-10" port port="1111" protocol="tcp" drop
        rule priority="-5" family="ipv4" source address="10.10.10.0/24" accept
        rule priority="-2" family="ipv4" source address="10.0.0.0/8" log
        rule priority="-1" family="ipv4" source address="10.0.0.0/8" drop
        rule service name="http" accept
        rule priority="1" service name="http" accept
        rule priority="10" service name="ssh" accept
        rule priority="100" service name="https" accept
        rule priority="125" service name="imap" accept
        rule priority="126" log prefix="DROPPED: "
        rule priority="127" drop
    ])])

FWD_END_TEST([-e '/INVALID_RULE: no element, no source, no destination/d'dnl
              -e '/INVALID_RULE: no element, no action/d'dnl
              -e '/ERROR: INVALID_PRIORITY: /d'dnl
              -e '/ERROR: Failed to write to file .*\/proc\/sys\/net\/ipv6\/conf\/all\/forwarding.*/d'])

FWD_START_TEST([rich rules bad])
    AT_KEYWORDS(rich)

    m4_define([rich_rule_test], [
        FWD_CHECK([--add-rich-rule='$1'], $2, ignore, ignore)
        FWD_CHECK([--permanent --add-rich-rule='$1'], $2, ignore, ignore)
    ])
    rich_rule_test([], 122) dnl empty
    rich_rule_test([name="dns" accept], 122) dnl no rule
    rich_rule_test([protocol value="ah" reject], 122) dnl no rule
    rich_rule_test([rule protocol value="ah" reject type="icmp-host-prohibited"], 122) dnl reject type needs specific family
    rich_rule_test([rule family="ipv4" protocol value="ah" reject type="dummy"], 122) dnl dummy reject type
    rich_rule_test([rule], 122) dnl no element
    rich_rule_test([rule bad_element], 122) dnl no unknown element
    rich_rule_test([rule family="ipv5"], 122) dnl bad family
    rich_rule_test([rule name="dns" accept], 122) dnl name outside of element
    rich_rule_test([rule protocol="ah" accept], 122) dnl bad protocol usage
    rich_rule_test([rule protocol value="ah" accept drop], 122) dnl accept && drop
    rich_rule_test([rule service name="radius" port port="4011" reject], 122) dnl service && port
    rich_rule_test([rule service bad_attribute="dns"], 122) dnl bad attribute
    rich_rule_test([rule protocol value="igmp" log level="eror"], 125) dnl bad log level
    IF_HOST_SUPPORTS_IPV6_RULES([
    rich_rule_test([family="ipv6" accept], 122) dnl no rule
    rich_rule_test([rule source address="1:2:3:4:6::" icmp-block name="redirect" log level="info" limit value="1/2m"], 207) dnl missing family
    rich_rule_test([rule family="ipv6" source address="1:2:3:4:6::" icmp-block name="redirect" log level="info" limit value="1/2m"], 123) dnl bad limit
    ])
    rich_rule_test([rule protocol value="esp"], 122) dnl no action/log/audit
    rich_rule_test([rule family="ipv4" masquerade drop], 122) dnl masquerade & action
    rich_rule_test([rule family="ipv4" icmp-block name="redirect" accept], 122) dnl icmp-block & action
    rich_rule_test([rule forward-port port="2222" to-port="22" protocol="tcp" family="ipv4" accept], 122) dnl forward-port & action
    m4_undefine([rich_rule_test])
FWD_END_TEST([-e '/ERROR: INVALID_RULE:/d' dnl
              -e '/ERROR: INVALID_LOG_LEVEL: eror/d' dnl
              -e '/ERROR: MISSING_FAMILY/d' dnl
              -e '/ERROR: INVALID_LIMIT: 1\/2m/d'])

FWD_START_TEST([config validation])
    AT_KEYWORDS(check_config)

    dnl default config
    FWD_CHECK([--check-config], 0, ignore)

    dnl The rest of these are negative test cases.

    dnl firewalld.conf
    AT_CHECK([cp ./firewalld.conf ./firewalld.conf.orig])
    AT_CHECK([echo "SomeBogusField=yes" >> ./firewalld.conf])
    FWD_CHECK([--check-config], 0, ignore, [dnl
m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [dnl
ERROR: Invalid option: 'SomeBogusField=yes'
ERROR: Invalid option: 'SomeBogusField=yes'
])])
    AT_CHECK([cp ./firewalld.conf.orig ./firewalld.conf])

    dnl direct
    AT_DATA([./direct.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<direct>
<chain table="filter" ipv="ipv7" chain="foobar"/>
</direct>
])
    FWD_CHECK([--check-config], 111, ignore, ignore)

    AT_DATA([./direct.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<direct>
<rule />
</direct>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)
    AT_CHECK([rm ./direct.xml])

    dnl lockdown-whitelist
    AT_DATA([./lockdown-whitelist.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<whitelist>
    <user uid="666"/>
</whitelist>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./lockdown-whitelist.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<whitelist>
    <uid id="666"/>
</whitelist>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./lockdown-whitelist.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<whitelist>
    <group name="foobar" />
</whitelist>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)
    AT_CHECK([rm ./lockdown-whitelist.xml])

    dnl ipset
    AT_CHECK([mkdir -p ./ipsets])
    AT_DATA([./ipsets/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<ipset type="hash:mac">
  <entry>12:34:56:78:90</entry>
</ipset>
])
    FWD_CHECK([--check-config], 0, ignore, [dnl
m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [dnl
WARNING: INVALID_ENTRY: invalid mac address '12:34:56:78:90' in '12:34:56:78:90', ignoring.
WARNING: INVALID_ENTRY: invalid mac address '12:34:56:78:90' in '12:34:56:78:90', ignoring.
])])

    AT_DATA([./ipsets/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<ipset type="hash:mac">
  <entry bogus_attr="bogus">12:34:56:78:90:ab</entry>
</ipset>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./ipsets/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<ipset type="hash:ip,bogus">
</ipset>
])
    FWD_CHECK([--check-config], 119, ignore, ignore)
    AT_CHECK([rm ./ipsets/foobar.xml])

    dnl helpers
    AT_CHECK([mkdir -p ./helpers])
    AT_DATA([./helpers/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<helper>
</helper>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./helpers/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<helper family="ipv7" module="nf_conntrack_ftp">
</helper>
])
    FWD_CHECK([--check-config], 111, ignore, ignore)

    IF_HOST_SUPPORTS_IPV6_RULES([
    AT_DATA([./helpers/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<helper family="ipv6" module="nf_conntrack_ftp">
<port protocol="aoeui" port="666" />
</helper>
])
    FWD_CHECK([--check-config], 103, ignore, ignore)
    ])
    AT_CHECK([rm ./helpers/foobar.xml])

    dnl icmptype
    AT_CHECK([mkdir -p ./icmptypes])
    AT_DATA([./icmptypes/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<bad_element />
<icmptype>
</icmptype>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./icmptypes/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<icmptype>
<destination unexpected_attr="foobar" />
</icmptype>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)
    AT_CHECK([rm ./icmptypes/foobar.xml])

    dnl services
    AT_CHECK([mkdir -p ./services])
    AT_DATA([./services/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<service>
<protocol value="aoeui" />
</service>
])
    FWD_CHECK([--check-config], 103, ignore, ignore)

    AT_DATA([./services/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<service>
<protocol bad_attr="foo" />
</service>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./services/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<service>
<bad_element />
</service>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./services/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<service>
<module module="bad_attr" />
</service>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./services/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<service>
<port protocol="aoeu" port="666" />
</service>
])
    FWD_CHECK([--check-config], 103, ignore, ignore)

    AT_DATA([./services/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<service>
<port protocol="tcp" port="ssssssh" />
</service>
])
    FWD_CHECK([--check-config], 102, ignore, ignore)

    AT_DATA([./services/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<service>
<port protocol="tcp" port="22" />
<source-port protocol="tcp" port="sssssh" />
</service>
])
    FWD_CHECK([--check-config], 102, ignore, ignore)

    AT_DATA([./services/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<service>
<destination ipv4="224.0.0.1" ipv7="1234" />
</service>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)
    AT_CHECK([rm ./services/foobar.xml])

    dnl zones
    AT_CHECK([mkdir -p ./zones])
    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
])
    FWD_CHECK([--check-config], 112, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<service name="bogus_service_name" />
</zone>
])
    FWD_CHECK([--check-config], 101, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<port protocol="ipv4" />
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<protocol value="thisdoesnotexist" />
</zone>
])
    FWD_CHECK([--check-config], 103, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<icmp-block invalid_attr=""/>
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<icmp-type />
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<masquerade value="true" />
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<forward-port port="666" />
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<forward-port protocol="sctppp" />
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<source-port port="-1" />
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<interface />
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<source />
</zone>
])
    FWD_CHECK([--check-config], 0, ignore, [dnl
m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [dnl
WARNING: Invalid source: No address no ipset.
WARNING: Invalid source: No address no ipset.
])])

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<rule>
<source address="10.0.0.1/24" />
<limit />
</rule>
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<rule family="ipv4">
<source address="10.0.0.1/24" />
<accept>
<limit value="none" />
</accept>
</rule>
</zone>
])
    FWD_CHECK([--check-config], 0, ignore, [dnl
m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [dnl
WARNING: INVALID_LIMIT: none: rule family="ipv4" source address="10.0.0.1/24" accept limit value="none"
WARNING: INVALID_LIMIT: none: rule family="ipv4" source address="10.0.0.1/24" accept limit value="none"
])])

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<rule>
<source address="10.0.0.1/24" />
<log level="super_critical" />
</rule>
</zone>
])
    FWD_CHECK([--check-config], 0, ignore, [dnl
m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [dnl
WARNING: Invalid rule: Invalid log level
WARNING: Invalid rule: Invalid log level
])])

    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<rule family="ipv4">
<source address="10.0.0.1/24" />
<audit prefix="foobar" />
</rule>
</zone>
])
    FWD_CHECK([--check-config], 28, ignore, ignore)

    IF_HOST_SUPPORTS_IPV6_RULES([
    AT_DATA([./zones/foobar.xml], [dnl
<?xml version="1.0" encoding="utf-8"?>
<zone>
<rule family="ipv6">
<source address="10.0.0.1/24" />
<accept />
</rule>
</zone>
])
    FWD_CHECK([--check-config], 0, ignore, [dnl
m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [dnl
WARNING: INVALID_ADDR: 10.0.0.1/24: rule family="ipv6" source address="10.0.0.1/24" accept
WARNING: INVALID_ADDR: 10.0.0.1/24: rule family="ipv6" source address="10.0.0.1/24" accept
])])
    ])
    AT_CHECK([rm ./zones/foobar.xml])

FWD_END_TEST([-e '/ERROR:/d'dnl
              -e '/WARNING:/d'])