timeformat protocol iso long;

# local addresses
{% if 'gates' in group_names %}
define local_addr_ffrl		= {{hostvar}}185.66.195.38;
define local_addr_icvpn		= {{hostvar}}10.207.37.161;  # ingwer = mwu161
define local_addr_mwu		= 10.37.0.{{mwu server id}};
{% else %}
define local_addr_mwu		= 10.37.1.{{mwu server id}};
{% endif %}

# AS
define mwu_as = 65037; # private AS of mwu
{% if 'gates' in group_names %}
define ffrl_as = 201701; # public AS of rheinland
{% endif %}

{% if 'gates' in group_names %}
router id local_addr_ffrl;

table ffrl;		# BGP Peerings FFRL

# ROA
roa table roa_icvpn {
    include "ebgp_roa_v4.inc";
}
{% else %}
router id local_addr_mwu;
{% endif %}

# 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() {
    return net ~ [
        10.56.0.0/16+,
        10.37.0.0/16+
    ];
}

function is_wi_self_net() {
    return net ~ [
        10.56.0.0/16+
    ];
}

function is_mz_self_net() {
    return net ~ [
        10.37.0.0/16+
    ];
}

{% if 'gates' in group_names %}
function is_local_addr_ffrl() {
    return net ~ [
        {{hostvar}}185.66.195.38/32
    ];
}

function is_ffrl_tunnel_nets() {
    return net ~ [
        {{hostvar}}100.64.2.234/31,
        {{hostvar}}100.64.2.236/31,
        {{hostvar}}100.64.2.238/31,
        {{hostvar}}100.64.2.240/31,
        {{hostvar}}100.64.1.112/31,
        {{hostvar}}100.64.1.114/31
    ];
}
{% endif %}

# filters
{% if 'gates' in group_names %}
filter ebgp_icvpn_import_filter {
    if is_mwu_self_nets() then reject;
    if is_chaosvpn() then accept;
    if roa_check(roa_icvpn) = ROA_VALID then {
        if is_freifunk() then accept;
        if is_dn42() then accept;
    } else {
        if roa_check(roa_icvpn) = ROA_UNKNOWN then {
            if is_dn42() then {
#                print "ROA UNKNOWN for dn42 net, accepting: ", net, " ASN: ", bgp_path.last;
                accept;
            }
            if is_freifunk() then {
#                print "ROA UNKNOWN for freifunk net, accepting: ", net, " ASN: ", bgp_path.last;
                accept;
            }
        }
        if roa_check(roa_icvpn) = ROA_INVALID then {
            if is_freifunk() then {
#                print "ROA INVALID for freifunk net, accept: ", net, " ASN: ", bgp_path.last;
                accept;
            }
        }
        reject;
    }
    reject;
}

filter ebgp_ffrl_import_filter {
    if is_default() then accept;
    reject;
}

filter ebgp_ffrl_export_filter {
    if is_local_addr_ffrl() then accept;
    reject;
}
{% else %}
# sanity check: don't allow critical overrides
filter ebgp_icvpn_import_filter {
    if is_mwu_self_nets() then reject;
    if is_default() then reject;
    if is_freifunk() then accept;
    if is_dn42() then accept;
    if is_chaosvpn() then accept;
    reject;
}
{% endif %}

# protocols
# necessary to inform bird about devices
protocol device {
    scan time 30;
};

protocol kernel kernel_mwu {
    scan time 30;
    import none;
    export filter {
        if is_mwu_self_nets() then
            reject;
        krt_prefsrc = local_addr_icvpn;
        accept;
    };
    kernel table ipt_icvpn;
};

{% if 'gates' in group_names %}
# learn about directly connected community subnets
protocol direct mwu_subnets {
    interface "mzBR";
    interface "wiBR";
    import where is_mwu_self_nets();
};

protocol static ffrl_uplink_hostroute {
    table ffrl;
    route 185.66.195.38/32 reject;
}

protocol direct ffrl_tunnels {
    table ffrl;
    interface "ffrl-*";
    import where is_ffrl_tunnel_nets();
}

protocol kernel kernel_ffrl {
    scan time 30;
    import none;
    export filter {
        krt_prefsrc = local_addr_ffrl;
        accept;
    };
    table ffrl;
    kernel table ipt_ffinetexit;
};
{% endif %}

# Templates
# templates for iBGP
{% if 'gates' in group_names %}
template bgp bgp_ibgp_mwu {
    local local_addr_mwu as mwu_as;
    import keep filtered on;
    import all;  # EXPERIMENT !!!!!
    export where source = RTS_BGP;
    direct;
    gateway direct;
};
{% else %}
template bgp bgp_ibgp_mwu {
    local local_addr_mwu as mwu_as;
    import filter ebgp_icvpn_import_filter;
    export none;
    direct;
    gateway direct;
};
{% endif %}

{% if 'gates' in group_names %}
# templates for eBGP
template bgp ebgp_ic {
    local local_addr_icvpn as mwu_as;
    import keep filtered on;
    import filter ebgp_icvpn_import_filter;
    export filter {
        if is_mwu_self_nets() then {  # own nets
            accept;
        }
        if source = RTS_BGP then {
            if is_freifunk() || is_dn42() then {
                accept;
            }
        }
        reject;
    };
    direct;
};

template bgp ffrl_uplink {
    table ffrl;
    local as mwu_as;
    import keep filtered;
    import filter ebgp_ffrl_import_filter;
    export filter ebgp_ffrl_export_filter;
    next hop self;
    direct;
};
{% endif %}

# P E E R I N G S
# iBGP 
include "mwu_peers_v4.inc";

{% if 'gates' in group_names %}
# P E E R I N G S
# eBGP FFRL exit
include "ffrl_peers_v4.inc";

# P E E R I N G S
# eBGP ICVPN
include "icvpn_peers_v4.inc";
{% endif %}