#
# {{ ansible_managed }}
#

# Variables
define router_id = {{ loopback_net_ipv4 | ipaddr('net') | ipaddr(magic) | ipaddr('address') }};
define loopback_address = {{ loopback_net_ipv4 | ipaddr('net') | ipaddr(magic) | ipaddr('address') }};
define mwu_address_legacy = {{ bgp_ipv4_transfer_net_legacy | ipaddr('net') | ipaddr(magic) | ipaddr('address') }};
define mwu_as = {{ as_private }};

# General
timeformat protocol iso long;
router id router_id;

# Functions
function is_default() {
    return net ~ [
        0.0.0.0/0
    ];
}

function is_freifunk() {
    return net ~ [
        10.0.0.0/8{16,24}
    ];
}

function is_dn42() {
    return net ~ [
        172.20.0.0/14{20,28}
    ];
}

function is_chaosvpn() {
    return net ~ [
        172.31.0.0/16+
    ];
}

function is_mwu_self_nets_loose() {
    return net ~ [
{% for prefix in internal_prefixes %}
        {{ prefix.ipv4 | ipaddr('net') }}+{{ "," if not loop.last else "" }}
{% endfor %}
    ];
}

function is_mwu_self_nets_strict() {
    return net ~ [
{% for prefix in internal_prefixes %}
        {{ prefix.ipv4 | ipaddr('net') }}{{ "," if not loop.last else "" }}
{% endfor %}
    ];
}

function is_mwu_loopback() {
    return net ~ [
        {{ loopback_net_ipv4 }}+
    ];
}

function is_mwu_anycast() {
    return net ~ [
        {{ anycast_ipv4 }}
    ];
}

# Protocols
protocol device {
    scan time 30;
};

protocol direct mwu_subnets {
{% if server_type == 'gateway' or server_type == 'monitoring' %}
{% for mesh in meshes %}
    interface "{{ mesh.id }}br";
{% endfor %}
{% endif %}
{% for network in my_wireguard_networks %}
    interface "wg-{{ network.remote[:11] }}";
{% endfor %}
    import where is_mwu_self_nets_loose();
};

protocol direct mwu_loopback {
    interface "loopback";
    import where is_mwu_loopback();
};

{% if server_type == "gateway" %}
protocol direct mwu_anycast {
    interface "anycast";
    import where is_mwu_anycast();
};

protocol static {
{% for prefix in internal_prefixes %}
    route {{ prefix.ipv4 }} reject;
{% endfor %}
};
{% endif %}

protocol kernel kernel_mwu {
    scan time 30;
    import none;
    export filter {
        krt_prefsrc = loopback_address;
{% if server_type == "gateway" %}
        if is_mwu_anycast() then reject;
{% else %}
        if is_mwu_anycast() then accept;
        if is_freifunk() then accept;
        if is_chaosvpn() then accept;
        if is_dn42() then accept;
{% endif %}
        if is_mwu_loopback() then accept;
        reject;
    };
    merge paths yes limit {{ groups['gateways'] | length }};
    kernel table ipt_mwu;
};

# Templates
template bgp ibgp_mwu {
    local as mwu_as;
    import keep filtered on;
    import filter {
{% if server_type == "gateway" %}
        if is_mwu_anycast() then reject;
{% endif %}
        if is_mwu_loopback() then accept;
        if is_mwu_self_nets_loose() then accept;
        if is_freifunk() then accept;
        if is_chaosvpn() then accept;
        if is_dn42() then accept;
        reject;
    };
    export filter {
{% if server_type == "gateway" %}
        if is_mwu_loopback() then accept;
        if is_mwu_self_nets_loose() then accept;
        if source = RTS_BGP then accept;
{% else %}
        if is_mwu_loopback() then accept;
{% endif %}
        reject;
    };
    direct;
    gateway direct;
};

# Include IPv4 MWU peers
include "mwu_ipv4_peers.con?";
{% if server_type == "gateway" %}

# Include IPv4 ICVPN configuration
include "icvpn_ipv4.con?";

# Include IPv4 FFRL configuration
include "ffrl_ipv4.con?";
{% endif %}