blob: 66d7e3623119b2ad54ddf29067826e606fc7201a [file] [log] [blame] [raw]
RNCN_UNPRIVILEGED_USER=rncn-noaccess
set -f
# Usage: update_route_cfg_file <ip4-networks-file> <ip4-router> <ip6-networks-file> <ip6-router> <cfg-dir>
update_route_cfg_file() {
local net
if [ -f "$1" ]; then
printf '# Generated from %s, on ' "$1"
date "+%F %T %Z"
while read net; do
grep --fixed-strings --line-regexp --quiet --silent "$net" "$5/ipv4-ra-exclusion" && continue
printf 'route %s via %s;\n' "$net" "$2"
done < "$1" 2> /dev/null
printf '# End of list from %s\n' "$1"
fi >> "$5/ipv4-ra"
if [ -n "$4" ] && [ -f "$3" ]; then
printf '# Generated from %s, on ' "$3"
date "+%F %T %Z"
while read net; do
grep --fixed-strings --line-regexp --quiet --silent "$net" "$5/ipv6-ra-exclusion" && continue
printf 'route %s via %s;\n' "$net" "$4"
done < "$3" 2> /dev/null
printf '# End of list from %s\n' "$1"
fi >> "$5/ipv6-ra"
}
# Usage: generate_fallback_route_filter <networks-file> <excluded-networks-file> <ip-version> <cfg-dir>
generate_fallback_route_filter() {
cat << EOT
export filter {
if
net ~ [
EOT
local net count=0
while read net; do
grep --fixed-strings --line-regexp --quiet --silent "$net" "$2" "$4/ipv$3-ra-exclusion" && continue
[ $count != 0 ] && echo ,
count=$((count+1))
printf " %s" "$net"
done < "$1" 2> /dev/null
cat << EOT
]
then {
ospf_metric1 = 100;
} else {
ospf_metric1 = 0;
}
accept;
};
EOT
} > "$4/ipv$3-export-to-ospf-filter"
is_inet4_address() {
[ "${1#.}" = "$1" ] && [ "${1%.}" = "$1" ] || return
local ORIG_IFS="$IFS"
IFS=.
set -- $1
IFS="$ORIG_IFS"
[ $# = 4 ] || return
local i=1 v
while [ $i -lt 5 ]; do
eval "v=\"\${$i}\""
[ "$v" -le 255 ] && [ "$v" -ge 0 ] || return
[ "$v" -gt 0 ] && [ "${v#0}" != "$v" ] && return 1
i=$((i+1))
done
[ $1 != 0 ] && return
[ $2 = 0 ] || return
[ $3 = 0 ] || return
[ $4 = 0 ] || return
true
}
is_inet6_address() {
printf %s\\n "$1" | grep -Eq '^\[(([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}|([0-9a-f]{1,4}:){1,6}:[0-9a-f]{1,4}|([0-9a-f]{1,4})?::([0-9a-f]{1,4})?)\]$'
}
run_filter() {
sudo -u "$RNCN_UNPRIVILEGED_USER" sh -c "$1"
}
process_url_file() {
url_file="$1"
output_dir="$2"
ip4_routes=""
ip6_routes=""
cfg_file_suffix=
# Read the URL file line by line
{
wget --no-verbose --no-cache --inet4-only "$url_file" -O -
echo
} | while read -r line; do
[ -z "$line" ] && continue
[ "${line#\#}" != "$line" ] && continue
set -- $line
case "$1" in
fallback)
cfg_file_suffix=-fallback
;;
end-fallback)
cfg_file_suffix=
;;
dig)
if [ $# != 2 ]; then
printf "Wrong number of arguments in '%s'\\n" "$line" 1>&2
continue
fi
domain="$2"
dig +short -t A "$domain" | while read record; do
if is_inet4_address "$record"; then
printf %s\\n "$record/32"
fi
done >> "$output_dir/ipv4-ra$cfg_file_suffix"
dig +short -t AAAA "$domain" | while read record; do
if is_inet6_address "$record"; then
printf %s\\n "$record/128"
fi
done >> "$output_dir/ipv6-ra$cfg_file_suffix"
;;
cidr)
if [ $# != 2 ]; then
printf "Wrong number of arguments in '%s'\\n" "$line" 1>&2
continue
fi
cidr_url="$2"
{
wget --no-verbose --no-cache --inet4-only "$cidr_url" -O -
echo
} | while read -r cidr_line; do
case "$cidr_line" in
*.*.*.*/*)
printf %s\\n "$cidr_line" >> "$output_dir/ipv4-ra$cfg_file_suffix"
;;
*::*/*)
printf %s\\n "$cidr_line" >> "$output_dir/ipv6-ra$cfg_file_suffix"
;;
esac
done
;;
parse-cidr)
if [ $# -lt 2 ]; then
printf "Wrong number of arguments in '%s'\\n" "$line" 1>&2
continue
fi
if ! read filter; then
printf "Failed to read filter command for '%s'\\n" "$line" 1>&2
break
fi
# Multiple URLs can be specified here as a failover mode
{
shift
for url in "$@"; do
wget --no-verbose --no-cache --inet4-only "$url" -O - && break
done
} | run_filter "$filter" | while read -r cidr_line; do
case "$cidr_line" in
*.*.*.*/*)
printf %s\\n "$cidr_line" >> "$output_dir/ipv4-ra$cfg_file_suffix"
;;
*::*/*)
printf %s\\n "$cidr_line" >> "$output_dir/ipv6-ra$cfg_file_suffix"
;;
esac
done
;;
*)
printf "Unrecognized directive '%s'\\n" "$1" 1>&2
;;
esac
done
}
if ! sudo -u "$RNCN_UNPRIVILEGED_USER" true; then
printf "Warning: can't switch to user '%s' for running filter command\\n" "$RNCN_UNPRIVILEGED_USER" 1>&2
fi
if [ "$#" -ne 1 ]; then
printf %s\\n "Usage: $0 <output-dir>" 1>&2
exit 1
fi
tmp_dir="`mktemp -d`"
trap 'rm -rf "$tmp_dir"' EXIT
trap 'rm -rf "$tmp_dir"; exit 255' INT TERM
trap "" HUP
while true; do
while read line; do
process_url_file "$line" "$tmp_dir"
done < /etc/bird/ra.list
rm -f "$1/ipv4-ra" "$1/ipv6-ra"
update_route_cfg_file "$tmp_dir/ipv4-ra" "$LOCAL_IP4_ROUTER" "$tmp_dir/ipv6-ra" "$LOCAL_IP6_ROUTER" "$1"
update_route_cfg_file "$tmp_dir/ipv4-ra-fallback" "$LOCAL_IP4_ROUTER" "$tmp_dir/ipv6-ra-fallback" "$LOCAL_IP6_ROUTER" "$1"
[ -f "$tmp_dir/ipv4-ra-fallback" ] && generate_fallback_route_filter "$tmp_dir/ipv4-ra-fallback" "$tmp_dir/ipv4-ra" 4 "$1"
[ -f "$tmp_dir/ipv6-ra-fallback" ] && generate_fallback_route_filter "$tmp_dir/ipv6-ra-fallback" "$tmp_dir/ipv6-ra" 6 "$1"
rm -f "$tmp_dir/ipv4-ra" "$tmp_dir/ipv6-ra" "$tmp_dir/ipv4-ra-fallback" "$tmp_dir/ipv6-ra-fallback"
sleep 3000
done