2021-04-10 14:52:13 +02:00
|
|
|
# Routing daemon configuration
|
2022-03-22 18:13:17 +01:00
|
|
|
{ hostName, config, lib, pkgs, ... }:
|
2021-03-25 04:06:53 +01:00
|
|
|
|
|
|
|
let
|
2022-09-18 00:17:59 +02:00
|
|
|
hostNameEscaped = builtins.replaceStrings [ "-" ] [ "_" ] hostName;
|
|
|
|
|
2021-03-25 04:06:53 +01:00
|
|
|
hostConf = config.site.hosts.${hostName};
|
2021-04-06 22:46:56 +02:00
|
|
|
|
2022-01-11 19:58:50 +01:00
|
|
|
upstreamInterfaces = lib.filterAttrs (_: { upstream, ... }:
|
|
|
|
upstream != null
|
|
|
|
) hostConf.interfaces;
|
|
|
|
|
2022-01-11 23:57:35 +01:00
|
|
|
isUpstream = upstreamInterfaces != {};
|
2021-04-29 01:44:48 +02:00
|
|
|
|
2022-10-23 01:16:18 +02:00
|
|
|
ipv6RouterNets = builtins.attrNames (
|
|
|
|
lib.filterAttrs (net: { ipv6Router, ... }:
|
|
|
|
ipv6Router == hostName
|
|
|
|
) config.site.net
|
|
|
|
);
|
2021-04-13 00:46:12 +02:00
|
|
|
|
|
|
|
enumerate = n: list:
|
|
|
|
if list == []
|
|
|
|
then []
|
|
|
|
else [ {
|
|
|
|
n = n;
|
|
|
|
x = builtins.head list;
|
|
|
|
} ] ++ (enumerate (n + 1) (builtins.tail list));
|
2021-03-25 04:06:53 +01:00
|
|
|
in
|
|
|
|
{
|
|
|
|
services.bird2 = {
|
|
|
|
enable = true;
|
|
|
|
config = ''
|
|
|
|
router id ${config.site.net.core.hosts4.${hostName}};
|
|
|
|
|
|
|
|
protocol kernel K4 {
|
2021-04-29 01:44:48 +02:00
|
|
|
learn;
|
2021-03-25 04:06:53 +01:00
|
|
|
ipv4 {
|
2021-05-02 19:51:48 +02:00
|
|
|
${if isUpstream
|
|
|
|
then ''
|
|
|
|
# Install all routes but the default route on upstreams
|
|
|
|
export where net != 0.0.0.0/0;
|
|
|
|
# Learn the upstream default route
|
|
|
|
import where net = 0.0.0.0/0;
|
|
|
|
''
|
|
|
|
else ''
|
|
|
|
export all;
|
2022-10-31 23:42:03 +01:00
|
|
|
''}
|
2021-03-25 04:06:53 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
protocol kernel K6 {
|
2021-04-29 01:44:48 +02:00
|
|
|
learn;
|
2021-03-25 04:06:53 +01:00
|
|
|
ipv6 {
|
2021-05-02 19:51:48 +02:00
|
|
|
${if isUpstream
|
|
|
|
then ''
|
|
|
|
# Install all routes but the default route on upstreams
|
|
|
|
export where net != ::/0;
|
|
|
|
# Learn the upstream default route
|
|
|
|
import where net = ::/0;
|
|
|
|
''
|
|
|
|
else ''
|
|
|
|
export all;
|
2022-10-31 23:42:03 +01:00
|
|
|
''}
|
2021-03-25 04:06:53 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
protocol device {
|
|
|
|
scan time 10;
|
|
|
|
}
|
2022-10-31 23:42:03 +01:00
|
|
|
# Import address ranges of upstream interfaces so that
|
|
|
|
# internal traffic to local public services take no detours
|
|
|
|
# if the default router takes another upstream gateway.
|
|
|
|
protocol direct {
|
|
|
|
ipv4 {
|
|
|
|
${if isUpstream
|
|
|
|
then ''
|
|
|
|
# No RFC1918, RFC6598
|
|
|
|
import where net !~ [ 100.64.0.0/10 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 ];
|
2022-11-01 00:03:17 +01:00
|
|
|
''
|
|
|
|
else ""}
|
2022-10-31 23:42:03 +01:00
|
|
|
};
|
2022-11-01 00:03:17 +01:00
|
|
|
ipv6;
|
2022-10-31 23:42:03 +01:00
|
|
|
interface ${lib.concatMapStringsSep ", " (iface:
|
|
|
|
''"${iface}"''
|
|
|
|
)(builtins.attrNames hostConf.interfaces)};
|
|
|
|
check link yes;
|
|
|
|
}
|
2021-03-25 04:06:53 +01:00
|
|
|
|
2022-09-18 00:39:25 +02:00
|
|
|
${lib.optionalString (
|
|
|
|
builtins.match "anon.*" hostName != null ||
|
|
|
|
hostName == "flpk-gw"
|
|
|
|
) ''
|
2021-04-30 22:39:56 +02:00
|
|
|
# BIRD routing table for Wireguard transport
|
2022-09-18 16:13:36 +02:00
|
|
|
ipv4 table vpn_table;
|
2021-04-29 22:46:03 +02:00
|
|
|
|
2021-04-30 22:39:56 +02:00
|
|
|
# Kernel routing table for Wireguard transport
|
2022-09-18 16:13:36 +02:00
|
|
|
protocol kernel VPN {
|
|
|
|
# "vpn_table" configured on anon routers
|
2021-04-29 22:46:03 +02:00
|
|
|
kernel table 100;
|
|
|
|
ipv4 {
|
|
|
|
export all;
|
2022-09-18 16:13:36 +02:00
|
|
|
table vpn_table;
|
2021-04-29 22:46:03 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
''}
|
|
|
|
|
2022-10-23 01:16:18 +02:00
|
|
|
${lib.optionalString (ipv6RouterNets != []) ''
|
2021-04-10 14:52:13 +02:00
|
|
|
# Router advertisements
|
|
|
|
protocol radv {
|
|
|
|
rdnss ${config.site.net.serv.hosts6.dn42.dnscache};
|
2021-04-06 22:46:56 +02:00
|
|
|
|
2022-10-23 01:18:27 +02:00
|
|
|
${lib.concatMapStrings (net: ''
|
2022-10-23 01:16:18 +02:00
|
|
|
interface "${net}" {
|
|
|
|
min ra interval 10;
|
|
|
|
max ra interval 60;
|
2021-04-06 22:46:56 +02:00
|
|
|
|
2022-10-23 01:16:18 +02:00
|
|
|
${builtins.concatStringsSep "\n" (
|
|
|
|
map (subnet6: ''
|
|
|
|
prefix ${subnet6} {
|
|
|
|
preferred lifetime 600;
|
|
|
|
valid lifetime 1800;
|
|
|
|
};
|
|
|
|
'') (builtins.attrValues config.site.net.${net}.subnets6)
|
|
|
|
)}
|
2021-04-06 22:46:56 +02:00
|
|
|
|
2022-10-23 01:16:18 +02:00
|
|
|
dnssl "${config.site.net.${net}.domainName}";
|
|
|
|
};
|
2022-10-23 01:18:27 +02:00
|
|
|
'') ipv6RouterNets}
|
2021-04-10 14:52:13 +02:00
|
|
|
}
|
2021-04-06 22:46:56 +02:00
|
|
|
''}
|
2021-03-25 04:06:53 +01:00
|
|
|
|
2021-04-10 14:52:13 +02:00
|
|
|
# OSPFv2 for site-local IPv4
|
2021-03-25 04:06:53 +01:00
|
|
|
protocol ospf v2 ZW4 {
|
2021-04-29 01:44:48 +02:00
|
|
|
ipv4 {
|
2022-11-01 00:38:24 +01:00
|
|
|
import all;
|
|
|
|
# OSPF is self-contained
|
|
|
|
export none;
|
2021-04-29 01:44:48 +02:00
|
|
|
};
|
2021-03-25 04:06:53 +01:00
|
|
|
area 0 {
|
|
|
|
${builtins.concatStringsSep "\n" (
|
|
|
|
builtins.attrValues (
|
|
|
|
builtins.mapAttrs (net: _:
|
2022-10-31 23:21:06 +01:00
|
|
|
# Enable OSPF only on networks with a secret.
|
2021-05-31 01:03:51 +02:00
|
|
|
if config.site.net ? "${net}" && config.site.net.${net}.ospf.secret != null
|
2021-03-25 04:06:53 +01:00
|
|
|
then ''
|
|
|
|
interface "${net}" {
|
2021-11-18 17:10:36 +01:00
|
|
|
hello 10;
|
|
|
|
wait 20;
|
2021-11-15 23:23:38 +01:00
|
|
|
|
2021-03-25 04:06:53 +01:00
|
|
|
authentication cryptographic;
|
|
|
|
password "${config.site.net.${net}.ospf.secret}";
|
|
|
|
};
|
|
|
|
''
|
2022-10-31 23:56:43 +01:00
|
|
|
else ''
|
|
|
|
interface "${net}" {
|
|
|
|
stub yes;
|
|
|
|
cost 10;
|
|
|
|
};
|
|
|
|
''
|
2021-03-25 04:06:53 +01:00
|
|
|
) hostConf.interfaces
|
|
|
|
)
|
|
|
|
)}
|
|
|
|
${builtins.concatStringsSep "\n" (
|
2021-04-10 14:52:13 +02:00
|
|
|
map (stubnet4: ''
|
|
|
|
# Advertise additional route
|
|
|
|
stubnet ${stubnet4} {};
|
|
|
|
'') hostConf.ospf.stubNets4
|
2021-03-25 04:06:53 +01:00
|
|
|
)}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-04-30 22:39:56 +02:00
|
|
|
${lib.optionalString isUpstream ''
|
|
|
|
# OSPFv2 to advertise my default route
|
2022-09-18 00:17:59 +02:00
|
|
|
protocol ospf v2 ZW4_${hostNameEscaped} {
|
2021-04-30 22:39:56 +02:00
|
|
|
ipv4 {
|
2021-04-30 23:02:31 +02:00
|
|
|
export where net = 0.0.0.0/0;
|
2021-04-30 22:39:56 +02:00
|
|
|
};
|
2021-04-30 23:54:36 +02:00
|
|
|
area 0 {
|
2021-04-30 22:39:56 +02:00
|
|
|
${builtins.concatStringsSep "\n" (
|
|
|
|
builtins.attrValues (
|
|
|
|
builtins.mapAttrs (net: _:
|
|
|
|
# Enable OSPF only on interfaces with a secret.
|
|
|
|
lib.optionalString (config.site.net.${net}.ospf.secret != null) ''
|
2021-04-30 23:54:36 +02:00
|
|
|
interface "${net}" instance ${toString hostConf.ospf.upstreamInstance} {
|
2021-05-02 20:01:59 +02:00
|
|
|
# Become the designated router
|
|
|
|
priority 10;
|
2021-11-18 17:10:36 +01:00
|
|
|
hello 10;
|
|
|
|
wait 20;
|
2021-05-02 20:01:59 +02:00
|
|
|
|
2021-04-30 22:39:56 +02:00
|
|
|
authentication cryptographic;
|
|
|
|
password "${config.site.net.${net}.ospf.secret}";
|
|
|
|
};
|
|
|
|
''
|
2021-05-31 00:06:56 +02:00
|
|
|
) hostConf.physicalInterfaces
|
2021-04-30 22:39:56 +02:00
|
|
|
)
|
|
|
|
)}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
''}
|
|
|
|
|
|
|
|
${(
|
2021-04-30 23:54:36 +02:00
|
|
|
builtins.foldl' ({ text, n }: upstream: {
|
2021-04-30 22:39:56 +02:00
|
|
|
text = ''
|
|
|
|
${text}
|
|
|
|
|
2021-04-30 23:54:36 +02:00
|
|
|
# OSPFv2 to receive a default route from ${upstream}
|
2022-09-18 01:47:40 +02:00
|
|
|
protocol ospf v2 ZW4_${
|
|
|
|
builtins.replaceStrings [ "-" ] [ "_" ] upstream
|
|
|
|
} {
|
2021-04-30 22:39:56 +02:00
|
|
|
ipv4 {
|
2021-04-30 23:54:36 +02:00
|
|
|
import filter {
|
|
|
|
preference = preference + ${toString (100 - n)};
|
2021-04-30 22:39:56 +02:00
|
|
|
accept;
|
|
|
|
};
|
2022-09-18 00:39:25 +02:00
|
|
|
${lib.optionalString (
|
|
|
|
builtins.match "anon.*" hostName != null ||
|
|
|
|
hostName == "flpk-gw"
|
|
|
|
) ''
|
2022-09-18 16:13:36 +02:00
|
|
|
table vpn_table;
|
2021-04-30 22:39:56 +02:00
|
|
|
''}
|
|
|
|
};
|
2021-04-30 23:54:36 +02:00
|
|
|
area 0 {
|
2021-04-30 22:39:56 +02:00
|
|
|
${builtins.concatStringsSep "\n" (
|
|
|
|
builtins.attrValues (
|
|
|
|
builtins.mapAttrs (net: _:
|
|
|
|
# Enable OSPF only on interfaces with a secret.
|
|
|
|
lib.optionalString (config.site.net.${net}.ospf.secret != null) ''
|
2022-09-18 01:37:57 +02:00
|
|
|
interface "${net}" instance ${
|
|
|
|
builtins.replaceStrings [ "-" ] [ "_" ] (
|
|
|
|
toString config.site.hosts.${upstream}.ospf.upstreamInstance
|
|
|
|
)
|
|
|
|
} {
|
2021-11-18 17:10:36 +01:00
|
|
|
hello 10;
|
|
|
|
wait 20;
|
2021-04-30 22:39:56 +02:00
|
|
|
authentication cryptographic;
|
|
|
|
password "${config.site.net.${net}.ospf.secret}";
|
|
|
|
};
|
|
|
|
''
|
2021-05-31 00:06:56 +02:00
|
|
|
) hostConf.physicalInterfaces
|
2021-04-30 22:39:56 +02:00
|
|
|
)
|
|
|
|
)}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
'';
|
2021-04-30 23:54:36 +02:00
|
|
|
n = n + 1;
|
|
|
|
}) { text = ""; n = 0; } hostConf.ospf.allowedUpstreams
|
2021-04-30 22:39:56 +02:00
|
|
|
).text}
|
|
|
|
|
2021-04-10 14:52:13 +02:00
|
|
|
# OSPFv3 for site-local IPv6
|
2021-03-25 04:06:53 +01:00
|
|
|
protocol ospf v3 ZW6 {
|
2021-04-29 01:44:48 +02:00
|
|
|
ipv6 {
|
2022-11-01 00:38:24 +01:00
|
|
|
import all;
|
|
|
|
# OSPF is self-contained
|
|
|
|
export none;
|
2021-04-29 01:44:48 +02:00
|
|
|
};
|
2021-03-25 04:06:53 +01:00
|
|
|
area 0 {
|
|
|
|
${builtins.concatStringsSep "\n" (
|
|
|
|
builtins.attrValues (
|
|
|
|
builtins.mapAttrs (net: _:
|
2022-10-31 23:21:06 +01:00
|
|
|
# Enable OSPF only on networks with a secret.
|
2021-03-25 04:06:53 +01:00
|
|
|
if config.site.net.${net}.ospf.secret != null
|
|
|
|
then ''
|
|
|
|
interface "${net}" {
|
2021-11-18 17:10:36 +01:00
|
|
|
hello 10;
|
|
|
|
wait 20;
|
2021-11-15 23:23:38 +01:00
|
|
|
|
2021-05-27 02:14:26 +02:00
|
|
|
authentication cryptographic;
|
|
|
|
password "${config.site.net.${net}.ospf.secret}";
|
2021-03-25 04:06:53 +01:00
|
|
|
};
|
|
|
|
''
|
2022-10-31 23:56:43 +01:00
|
|
|
else ''
|
|
|
|
interface "${net}" {
|
|
|
|
stub yes;
|
|
|
|
cost 10;
|
|
|
|
};
|
|
|
|
''
|
2021-05-31 00:06:56 +02:00
|
|
|
) hostConf.physicalInterfaces
|
2021-03-25 04:06:53 +01:00
|
|
|
)
|
|
|
|
)}
|
|
|
|
${builtins.concatStringsSep "\n" (
|
2021-04-10 14:52:13 +02:00
|
|
|
map (stubnet6: ''
|
|
|
|
# Advertise additional route
|
|
|
|
stubnet ${stubnet6} {};
|
|
|
|
'')
|
2021-03-25 04:06:53 +01:00
|
|
|
hostConf.ospf.stubNets6
|
|
|
|
)}
|
|
|
|
};
|
|
|
|
}
|
2021-04-13 00:46:12 +02:00
|
|
|
|
2021-04-30 22:39:56 +02:00
|
|
|
${lib.optionalString isUpstream ''
|
|
|
|
# OSPFv3 to advertise my default route
|
2022-09-18 00:17:59 +02:00
|
|
|
protocol ospf v3 ZW6_${hostNameEscaped} {
|
2021-04-30 22:39:56 +02:00
|
|
|
ipv6 {
|
2021-04-30 23:02:31 +02:00
|
|
|
export where net = ::/0;
|
2021-04-30 22:39:56 +02:00
|
|
|
};
|
2021-04-30 23:54:36 +02:00
|
|
|
area 0 {
|
2021-04-30 22:39:56 +02:00
|
|
|
${builtins.concatStringsSep "\n" (
|
|
|
|
builtins.attrValues (
|
|
|
|
builtins.mapAttrs (net: _:
|
|
|
|
# Enable OSPF only on interfaces with a secret.
|
|
|
|
lib.optionalString (config.site.net.${net}.ospf.secret != null) ''
|
2021-04-30 23:54:36 +02:00
|
|
|
interface "${net}" instance ${toString hostConf.ospf.upstreamInstance} {
|
2021-05-02 20:01:59 +02:00
|
|
|
# Become the designated router
|
|
|
|
priority 10;
|
2021-11-18 17:10:36 +01:00
|
|
|
hello 10;
|
|
|
|
wait 20;
|
2021-05-02 20:01:59 +02:00
|
|
|
|
2021-05-27 02:14:26 +02:00
|
|
|
authentication cryptographic;
|
|
|
|
password "${config.site.net.${net}.ospf.secret}";
|
2021-04-30 22:39:56 +02:00
|
|
|
};
|
|
|
|
''
|
2021-05-31 00:06:56 +02:00
|
|
|
) hostConf.physicalInterfaces
|
2021-04-30 22:39:56 +02:00
|
|
|
)
|
|
|
|
)}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
''}
|
|
|
|
|
2021-04-30 23:54:36 +02:00
|
|
|
${lib.optionalString (builtins.match "anon.*" hostName == null) (
|
|
|
|
builtins.foldl' ({ text, n }: upstream: {
|
2021-04-30 22:39:56 +02:00
|
|
|
text = ''
|
|
|
|
${text}
|
|
|
|
|
2021-04-30 23:54:36 +02:00
|
|
|
# OSPFv3 to receive a default route from ${upstream}
|
2022-09-18 01:47:40 +02:00
|
|
|
protocol ospf v3 ZW6_${
|
|
|
|
builtins.replaceStrings [ "-" ] [ "_" ] upstream
|
|
|
|
} {
|
2021-04-30 22:39:56 +02:00
|
|
|
ipv6 {
|
2021-04-30 23:54:36 +02:00
|
|
|
import filter {
|
|
|
|
preference = preference + ${toString (100 - n)};
|
2021-04-30 22:39:56 +02:00
|
|
|
accept;
|
|
|
|
};
|
|
|
|
};
|
2021-04-30 23:54:36 +02:00
|
|
|
area 0 {
|
2021-04-30 22:39:56 +02:00
|
|
|
${builtins.concatStringsSep "\n" (
|
|
|
|
builtins.attrValues (
|
|
|
|
builtins.mapAttrs (net: _:
|
|
|
|
# Enable OSPF only on interfaces with a secret.
|
|
|
|
lib.optionalString (config.site.net.${net}.ospf.secret != null) ''
|
2022-09-18 01:37:57 +02:00
|
|
|
interface "${net}" instance ${
|
|
|
|
builtins.replaceStrings [ "-" ] [ "_" ] (
|
|
|
|
toString config.site.hosts.${upstream}.ospf.upstreamInstance
|
|
|
|
)
|
|
|
|
} {
|
2021-11-18 17:10:36 +01:00
|
|
|
hello 10;
|
|
|
|
wait 20;
|
2021-05-27 02:14:26 +02:00
|
|
|
authentication cryptographic;
|
|
|
|
password "${config.site.net.${net}.ospf.secret}";
|
2021-04-30 22:39:56 +02:00
|
|
|
};
|
|
|
|
''
|
2021-05-31 00:06:56 +02:00
|
|
|
) hostConf.physicalInterfaces
|
2021-04-30 22:39:56 +02:00
|
|
|
)
|
|
|
|
)}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
'';
|
2021-04-30 23:54:36 +02:00
|
|
|
n = n + 1;
|
2022-09-18 01:37:57 +02:00
|
|
|
}) { text = ""; n = 0; } hostConf.ospf.allowedUpstreams6
|
2021-04-30 22:39:56 +02:00
|
|
|
).text}
|
|
|
|
|
2021-04-13 00:46:12 +02:00
|
|
|
# Zentralwerk DN42
|
|
|
|
protocol static {
|
|
|
|
ipv4;
|
|
|
|
route 172.20.72.0/21 unreachable;
|
|
|
|
}
|
|
|
|
protocol static {
|
|
|
|
ipv6;
|
|
|
|
route fd23:42:c3d2:580::/57 unreachable;
|
2021-06-02 19:56:24 +02:00
|
|
|
route 2a00:8180:2c00:200::/56 unreachable;
|
2022-09-18 01:57:31 +02:00
|
|
|
route 2a0f:5382:acab:1400::/56 unreachable;
|
2021-04-13 00:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
${lib.optionalString (hostConf.bgp != null) ''
|
|
|
|
template bgp bgppeer {
|
|
|
|
local as ${toString hostConf.bgp.asn};
|
|
|
|
|
|
|
|
ipv4 {
|
|
|
|
import all;
|
|
|
|
export where source=RTS_STATIC;
|
|
|
|
};
|
|
|
|
ipv6 {
|
|
|
|
import all;
|
|
|
|
export where source=RTS_STATIC;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
${builtins.concatStringsSep "\n" (
|
|
|
|
map ({ n, x }:
|
|
|
|
let
|
|
|
|
peer = x;
|
|
|
|
peerConf = hostConf.bgp.peers.${peer};
|
|
|
|
in ''
|
|
|
|
protocol bgp bgp_${toString n} from bgppeer {
|
|
|
|
neighbor ${peer} as ${toString peerConf.asn};
|
|
|
|
}
|
|
|
|
''
|
|
|
|
) (enumerate 1 (builtins.attrNames hostConf.bgp.peers))
|
|
|
|
)}
|
|
|
|
''}
|
2021-03-25 04:06:53 +01:00
|
|
|
'';
|
|
|
|
};
|
2021-05-05 17:35:44 +02:00
|
|
|
|
|
|
|
# Script that pings internet hosts every few minutes to determine if
|
|
|
|
# the upstream actually works. The associated OSPF instance will be
|
|
|
|
# enabled/disabled on state change.
|
|
|
|
systemd.services =
|
|
|
|
let
|
|
|
|
interval = 5;
|
|
|
|
targets = {
|
|
|
|
ipv4 = [
|
|
|
|
# inbert.c3d2.de
|
|
|
|
"217.197.83.184"
|
|
|
|
# ccc.de
|
|
|
|
"195.54.164.39"
|
|
|
|
# Cloud DNS services
|
|
|
|
"9.9.9.9"
|
|
|
|
"8.8.8.8"
|
|
|
|
"1.1.1.1"
|
|
|
|
];
|
|
|
|
ipv6 = [
|
|
|
|
# inbert.c3d2.de
|
|
|
|
"2001:67c:1400:2240::1"
|
|
|
|
# ccc.de
|
|
|
|
"2001:67c:20a0:2:0:164:0:39"
|
|
|
|
# Cloud DNS services
|
|
|
|
"2620:fe::9"
|
|
|
|
"2606:4700:4700::1111"
|
|
|
|
"2001:4860:4860::8888"
|
|
|
|
];
|
|
|
|
};
|
|
|
|
instance = {
|
2022-09-18 00:17:59 +02:00
|
|
|
ipv4 = "ZW4_${hostNameEscaped}";
|
|
|
|
ipv6 = "ZW6_${hostNameEscaped}";
|
2021-05-05 17:35:44 +02:00
|
|
|
};
|
|
|
|
checkService = addressFamily: {
|
|
|
|
description = "Check connectivity for ${addressFamily}";
|
|
|
|
after = [ "network.target" ];
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
serviceConfig = {
|
|
|
|
User = "bird2";
|
|
|
|
Group = "bird2";
|
|
|
|
};
|
|
|
|
path = [ pkgs.bird2 "/run/wrappers" ];
|
|
|
|
script = ''
|
|
|
|
STATE=unknown
|
|
|
|
|
|
|
|
while true; do
|
|
|
|
NEW_STATE=unknown
|
|
|
|
false \
|
|
|
|
${lib.concatMapStrings (target:
|
|
|
|
" || ping -n -s 0 -c 1 -w 1 ${target} 2>/dev/null >/dev/null \\\n"
|
|
|
|
) targets.${addressFamily}} \
|
|
|
|
&& NEW_STATE=up \
|
|
|
|
|| NEW_STATE=down
|
|
|
|
|
|
|
|
if [ $STATE != $NEW_STATE ]; then
|
|
|
|
echo "Connectivity change from $STATE to $NEW_STATE"
|
|
|
|
if [ $NEW_STATE = up ]; then
|
|
|
|
birdc enable ${instance.${addressFamily}}
|
|
|
|
else
|
|
|
|
birdc disable ${instance.${addressFamily}}
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
STATE=$NEW_STATE
|
|
|
|
sleep ${toString interval}
|
|
|
|
done
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
in lib.mkIf isUpstream {
|
|
|
|
check-upstream-ipv4 = checkService "ipv4";
|
|
|
|
check-upstream-ipv6 = checkService "ipv6";
|
|
|
|
};
|
2021-03-25 04:06:53 +01:00
|
|
|
}
|