#!/bin/sh

# DynamicIPv6Aliases v1.3
# 
# Erkennt ein sich änderndes, öffentliches IPv6 Netzwerk/
# Präfix (inet6 autoconf) und kann darauf reagieren. Gedacht
# für sich häufig ändernde Netzadressen bei privat ISPs.
# Geschrieben für OpenBSD.

# # crontab -l
# ...
# * * * * * /etc/IPv6Aliases.sh re0

interface=$1

change() {
	newIPv6Net=$1
	oldIPv6Net=$2
	echo Neu: $newIPv6Net
	echo Alt: $oldIPv6Net
	
	# Eigenen Anpassungen hier eintragen:
	
	# Was auch immer getan werden muss um Configs 
	# anzupassen und Dienste neu zu starten.
	
	# Zum Beispiel:
	# Email
	ifconfig $interface inet6 alias $newIPv6Net:1:2:3:4
	
	echo "v6adr = $newIPv6Net:1:2:3:4" > /etc/mail/v6adr
	rcctl restart smtpd
	
	# Update DynDNS
	ftp -o /dev/null "https://user:pass@dyndns.example.com/nic/update?myipv6=$newIPv6Net:1:2:3:4" > /dev/null
	
	
	# Web
	ifconfig $interface inet6 alias $newIPv6Net:a:b:c:d
	
	sed -iOv6 "s/Nv6adr\ \=.*/Nv6adr\ \=\ $newIPv6Net:a:b:c:d/g" /etc/httpd.conf
	
	rcctl check httpd > /dev/null
	if [ $? -eq 0 ]; then
		rcctl reload httpd
	else
		rcctl restart httpd
	fi
	
	
	# Alte Adressen ablöschen
	if [ "$oldIPv6Net" != "" ]
	then
		# Email
		ifconfig $interface inet6 delete $oldIPv6Net:1:2:3:4
		# Web
		ifconfig $interface inet6 delete $oldIPv6Net:a:b:c:d
	fi
	
	# Ende der eigenen Anpassungen!
}


[ "$interface" == "" ] && echo Usage: $0 network-interface && exit 1

# Falls das System eben gerade erst gebootet ist, noch nicht ausführen.
# Zeit geben bis alles oben ist.
uptime=`echo $(( $(date +%s) - $(sysctl -n kern.boottime) ))`
[ $uptime -lt 120 ] && exit

# route -n show -inet6 | grep $interface = Alle IPv6 Netze und Adressen auflisten.
# grep ::/64 = Nur Netzadressen anzeigen.
# grep -vE '^(fc|fd|fe[8-9 a-f])' = Nicht routbare Netze entfernen.
#   Konnten sich manchmal einschleichen wenn der Router kein öffentliches
#   IPv6-Netz zum verteilen hatte. Z.B. wegen einer Internetstörung.
#     fc|fd = fc00::/7 ULA, Unique Local IPv6 Unicast Addresses, RFC 4193
#     fe8|fe9|fea|feb = fe80::/10, Link-Local IPv6 Unicast Addresses, RFC 4291
#     fec|fed|fee|fef = fec0::/10, Site-Local IPv6 Unicast Addresses, RFC 4291
# awk -F "::/64" '{print substr($1,1,19)}' = Rein auf das Präfix verkürzen.
# tail -n 1 = Später hinzugefügte Netze stehen unten. Letzter Eintrag also neustes IPv6-Präfix.
publicIPv6Net=`route -n show -inet6 | grep $interface \
               | grep ::/64 | grep -vE '^(fc|fd|fe[8-9 a-f])' \
               | awk -F "::/64" '{print substr($1,1,19)}' \
               | tail -n 1`

[ "$publicIPv6Net" == "" ] && exit

if [ ! -f /tmp/lastPublicIPv6Net-$interface ] \
|| [ "$publicIPv6Net" != "`cat /tmp/lastPublicIPv6Net-$interface`" ]
then
	lastPublicIPv6Net=`cat /tmp/lastPublicIPv6Net-$interface` 2> /dev/null
	echo $publicIPv6Net > /tmp/lastPublicIPv6Net-$interface
	change "$publicIPv6Net" "$lastPublicIPv6Net"
fi
