#!/usr/bin/sh

# bogon2rtbh
# Remotely Triggered Black Hole (RTBH)
# Team Cymru Bogon Reference importer
# downloads Bogons via HTTP (IPv4/IPv6) and imports them into the Quagga BOGON table
# items are added/deleted daily as needed to maintain sychronization

#CHANGELOG
#0.50	start development
#0.60	filter IPv6 prefix sizes according to INI file
#0.61   add slight delay between rtbh-ctl commands

set -o errexit
#set -o pipefail
set -o nounset
#set -o xtrace

RTBH_TYPE='BOGON'
WORK_DIR='/var/cache/rtbh'
CTL_PROG='rtbh-ctl'
CONF='/usr/local/etc/bogon2rtbh.ini'

# http://www.team-cymru.org/bogon-reference-http.html
BOGON_BASE_URL='http://www.team-cymru.org/Services/Bogons/'
BOGON_FILE_BASE='fullbogons-ipv'
BOGON_FILE_EXT='.txt'

DELAY_RANDOM_MAX=240
#IPV6_NETMASK_MAX=128	# accept all by default
#FRRouting 7.5 appears to have an invisible cap of ~60k
#but the whole BOGON table is ~140k as of 2024-05
IPV6_NETMASK_MAX=27	# FRR 7.5 workaround

if [ -s $CONF ]; then
	. $CONF
fi

cd $WORK_DIR # expected to fail when rtbh-init not used yet

# delay only when running under CRON
if [ -n "${MAILTO+xxx}" ]; then
	DELAY=$(( RANDOM % DELAY_RANDOM_MAX ))
	echo "desynchronization adjustment of $DELAY second(s)"
	sleep $DELAY
fi

syscheck restrict bogon2rtbh 900

# https://en.wikipedia.org/wiki/Reserved_IP_addresses
LIST_FILTER=$(mktemp)
cat > $LIST_FILTER << EOF
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
100.64.0.0/10
EOF

# obtain bogon text files for both address families
LIST_CYMRU=$(mktemp)
for AF in 4 6; do
	FILENAME="${BOGON_FILE_BASE}${AF}${BOGON_FILE_EXT}"
	wget --timestamping ${BOGON_BASE_URL}$FILENAME
	case $AF in
		4)
		awk '{ if ($1!="#") print } ' $FILENAME |
		grep --fixed-strings --file=$LIST_FILTER --invert-match >> $LIST_CYMRU
		;;

		6)
		while IFS=/ read ADDRESS MASK; do
			if [ "${ADDRESS#\#}" != "$ADDRESS" -o -z "$MASK" ]; then
				continue
			elif [ $MASK -le $IPV6_NETMASK_MAX ]; then
				echo $ADDRESS/$MASK >> $LIST_CYMRU
			fi
		done < $FILENAME
		;;
	esac
done
rm $LIST_FILTER

LIST_BGPD=$(mktemp)
$CTL_PROG --table $RTBH_TYPE --list > $LIST_BGPD

ADD=$(mktemp)
if grep --fixed-strings --file=$LIST_BGPD --invert-match $LIST_CYMRU > $ADD; then
	for BOGON in $(cat $ADD); do
		$CTL_PROG --verbose --volatile --table $RTBH_TYPE --append $BOGON
	done
	$CTL_PROG --verbose --commit
    sleep 0.1 # Slight delay to avoid clobbering VTYSH
fi
rm $ADD

DEL=$(mktemp)
if grep --fixed-strings --file=$LIST_CYMRU --invert-match $LIST_BGPD > $DEL; then
	for BOGON in $(cat $DEL); do
		$CTL_PROG --verbose --volatile --table $RTBH_TYPE --delete $BOGON
	done
	$CTL_PROG --verbose --commit
    sleep 0.1 # Slight delay to avoid clobbering VTYSH
fi
rm $DEL

rm $LIST_BGPD $LIST_CYMRU

syscheck release bogon2rtbh

# vim: cindent:shiftwidth=4:tabstop=4:smarttab:textwidth=100
