#!/usr/sbin/nft -f

{% if cleanup_commands is vyos_defined %}
{%   for command in cleanup_commands %}
{{ command }}
{%   endfor %}
{% endif %}

include "/run/nftables_defines.conf"

table ip filter {
{% if first_install is vyos_defined %}
    chain VYOS_FW_FORWARD {
        type filter hook forward priority 0; policy accept;
        jump VYOS_POST_FW
    }
    chain VYOS_FW_LOCAL {
        type filter hook input priority 0; policy accept;
        jump VYOS_POST_FW
    }
    chain VYOS_FW_OUTPUT {
        type filter hook output priority 0; policy accept;
        jump VYOS_POST_FW
    }
    chain VYOS_POST_FW {
        return
    }
    chain VYOS_FRAG_MARK {
        type filter hook prerouting priority -450; policy accept;
        ip frag-off & 0x3fff != 0 meta mark set 0xffff1 return
    }
{% endif %}
{% if name is vyos_defined %}
{%   set ns = namespace(sets=[]) %}
{%   for name_text, conf in name.items() %}
    chain NAME_{{ name_text }} {
{%     if conf.rule is vyos_defined %}
{%       for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
        {{ rule_conf | nft_rule(name_text, rule_id) }}
{%         if rule_conf.recent is vyos_defined %}
{%           set ns.sets = ns.sets + [name_text + '_' + rule_id] %}
{%         endif %}
{%       endfor %}
{%     endif %}
        {{ conf | nft_default_rule(name_text) }}
    }
{%   endfor %}
{%   for set_name in ns.sets %}
    set RECENT_{{ set_name }} {
        type ipv4_addr
        size 65535
        flags dynamic
    }
{%   endfor %}
{% endif %}
{% if state_policy is vyos_defined %}
    chain VYOS_STATE_POLICY {
{%   if state_policy.established is vyos_defined %}
        {{ state_policy.established | nft_state_policy('established') }}
{%   endif %}
{%   if state_policy.invalid is vyos_defined %}
        {{ state_policy.invalid | nft_state_policy('invalid') }}
{%   endif %}
{%   if state_policy.related is vyos_defined %}
        {{ state_policy.related | nft_state_policy('related') }}
{%   endif %}
        return
    }
{% endif %}
}

table ip6 filter {
{% if first_install is vyos_defined %}
    chain VYOS_FW6_FORWARD {
        type filter hook forward priority 0; policy accept;
        jump VYOS_POST_FW6
    }
    chain VYOS_FW6_LOCAL {
        type filter hook input priority 0; policy accept;
        jump VYOS_POST_FW6
    }
    chain VYOS_FW6_OUTPUT {
        type filter hook output priority 0; policy accept;
        jump VYOS_POST_FW6
    }
    chain VYOS_POST_FW6 {
        return
    }
    chain VYOS_FRAG6_MARK {
        type filter hook prerouting priority -450; policy accept;
        exthdr frag exists meta mark set 0xffff1 return
    }
{% endif %}
{% if ipv6_name is vyos_defined %}
{%   set ns = namespace(sets=[]) %}
{%   for name_text, conf in ipv6_name.items() %}
    chain NAME6_{{ name_text }} {
{%     if conf.rule is vyos_defined %}
{%       for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
        {{ rule_conf | nft_rule(name_text, rule_id, 'ip6') }}
{%         if rule_conf.recent is vyos_defined %}
{%           set ns.sets = ns.sets + [name_text + '_' + rule_id] %}
{%         endif %}
{%       endfor %}
{%     endif %}
        {{ conf | nft_default_rule(name_text) }}
    }
{%   endfor %}
{%   for set_name in ns.sets %}
    set RECENT6_{{ set_name }} {
        type ipv6_addr
        size 65535
        flags dynamic
    }
{%   endfor %}
{% endif %}
{% if state_policy is vyos_defined %}
    chain VYOS_STATE_POLICY6 {
{%   if state_policy.established is vyos_defined %}
        {{ state_policy.established | nft_state_policy('established', ipv6=True) }}
{%   endif %}
{%   if state_policy.invalid is vyos_defined %}
        {{ state_policy.invalid | nft_state_policy('invalid', ipv6=True) }}
{%   endif %}
{%   if state_policy.related is vyos_defined %}
        {{ state_policy.related | nft_state_policy('related', ipv6=True) }}
{%   endif %}
        return
    }
{% endif %}
}

{% if first_install is vyos_defined %}
table ip nat {
    chain PREROUTING {
        type nat hook prerouting priority -100; policy accept;
        counter jump VYOS_PRE_DNAT_HOOK
    }

    chain POSTROUTING {
        type nat hook postrouting priority 100; policy accept;
        counter jump VYOS_PRE_SNAT_HOOK
    }

    chain VYOS_PRE_DNAT_HOOK {
        return
    }

    chain VYOS_PRE_SNAT_HOOK {
        return
    }
}

table ip6 nat {
    chain PREROUTING {
        type nat hook prerouting priority -100; policy accept;
        counter jump VYOS_DNPT_HOOK
    }

    chain POSTROUTING {
        type nat hook postrouting priority 100; policy accept;
        counter jump VYOS_SNPT_HOOK
    }

    chain VYOS_DNPT_HOOK {
        return
    }

    chain VYOS_SNPT_HOOK {
        return
    }
}

table inet mangle {
    chain FORWARD {
        type filter hook forward priority -150; policy accept;
    }
}

table raw {
    chain VYOS_TCP_MSS {
        type filter hook forward priority -300; policy accept;
    }

    chain PREROUTING {
        type filter hook prerouting priority -200; policy accept;
        counter jump VYOS_CT_IGNORE
        counter jump VYOS_CT_TIMEOUT
        counter jump VYOS_CT_PREROUTING_HOOK
        counter jump FW_CONNTRACK
        notrack
    }

    chain OUTPUT {
        type filter hook output priority -200; policy accept;
        counter jump VYOS_CT_IGNORE
        counter jump VYOS_CT_TIMEOUT
        counter jump VYOS_CT_OUTPUT_HOOK
        counter jump FW_CONNTRACK
        notrack
    }

    ct helper rpc_tcp {
        type "rpc" protocol tcp;
    }

    ct helper rpc_udp {
        type "rpc" protocol udp;
    }

    ct helper tns_tcp {
        type "tns" protocol tcp;
    }

    chain VYOS_CT_HELPER {
        ct helper set "rpc_tcp" tcp dport {111} return
        ct helper set "rpc_udp" udp dport {111} return
        ct helper set "tns_tcp" tcp dport {1521,1525,1536} return
        return
    }

    chain VYOS_CT_IGNORE {
        return
    }

    chain VYOS_CT_TIMEOUT {
        return
    }

    chain VYOS_CT_PREROUTING_HOOK {
        return
    }

    chain VYOS_CT_OUTPUT_HOOK {
        return
    }

    chain FW_CONNTRACK {
        accept
    }
}

table ip6 raw {
    chain VYOS_TCP_MSS {
        type filter hook forward priority -300; policy accept;
    }

    chain PREROUTING {
        type filter hook prerouting priority -300; policy accept;
        counter jump VYOS_CT_PREROUTING_HOOK
        counter jump FW_CONNTRACK
        notrack
    }

    chain OUTPUT {
        type filter hook output priority -300; policy accept;
        counter jump VYOS_CT_OUTPUT_HOOK
        counter jump FW_CONNTRACK
        notrack
    }

    chain VYOS_CT_PREROUTING_HOOK {
        return
    }

    chain VYOS_CT_OUTPUT_HOOK {
        return
    }

    chain FW_CONNTRACK {
        accept
    }
}
{% endif %}