From fb40bb3c0637e984fa4f43c7c2837e19c47e950e Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Mon, 19 Mar 2012 21:10:04 +0000
Subject: [PATCH] 6in4: add netifd support

SVN-Revision: 31036
---
 package/6in4/Makefile               |  17 +++-
 package/6in4/files.old/6in4.hotplug |  68 +++++++++++++
 package/6in4/files.old/6in4.sh      | 104 ++++++++++++++++++++
 package/6in4/files/6in4.hotplug     |  47 +--------
 package/6in4/files/6in4.sh          | 146 +++++++++++++++++-----------
 5 files changed, 279 insertions(+), 103 deletions(-)
 create mode 100644 package/6in4/files.old/6in4.hotplug
 create mode 100755 package/6in4/files.old/6in4.sh

diff --git a/package/6in4/Makefile b/package/6in4/Makefile
index fb0803a8a6..ee53f5e3ca 100644
--- a/package/6in4/Makefile
+++ b/package/6in4/Makefile
@@ -34,11 +34,20 @@ endef
 define Build/Configure
 endef
 
-define Package/6in4/install
-	$(INSTALL_DIR) $(1)/lib/network
-	$(INSTALL_DATA) ./files/6in4.sh $(1)/lib/network/6in4.sh
+ifneq ($(CONFIG_PACKAGE_netifd),)
+  define Package/6in4/install
+	$(INSTALL_DIR) $(1)/lib/netifd/proto
+	$(INSTALL_BIN) ./files/6in4.sh $(1)/lib/netifd/proto/6in4.sh
 	$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
 	$(INSTALL_DATA) ./files/6in4.hotplug $(1)/etc/hotplug.d/iface/90-6in4
-endef
+  endef
+else
+  define Package/6in4/install
+	$(INSTALL_DIR) $(1)/lib/network
+	$(INSTALL_DATA) ./files.old/6in4.sh $(1)/lib/network/6in4.sh
+	$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
+	$(INSTALL_DATA) ./files.old/6in4.hotplug $(1)/etc/hotplug.d/iface/90-6in4
+  endef
+endif
 
 $(eval $(call BuildPackage,6in4))
diff --git a/package/6in4/files.old/6in4.hotplug b/package/6in4/files.old/6in4.hotplug
new file mode 100644
index 0000000000..3d9def448e
--- /dev/null
+++ b/package/6in4/files.old/6in4.hotplug
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+if [ "$ACTION" = ifup ]; then
+	. /etc/functions.sh
+
+	include /lib/network
+	scan_interfaces
+
+	update_tunnel() {
+		local cfg="$1"
+
+		local proto
+		config_get proto "$cfg" proto
+		[ "$proto" = 6in4 ] || return 0
+
+		local wandev
+		config_get wandev "$cfg" wan_device "$(find_6in4_wanif)"
+		[ "$wandev" = "$DEVICE" ] || return 0
+
+		local wanip=$(find_6in4_wanip "$wandev")
+
+		[ -n "$wanip" ] && {
+			lsmod | grep -q ^sit || {
+				logger -t 6in4-update "Tunneling driver not loaded yet, deferring action"
+				exit 0
+			}
+
+			local tunnelid
+			config_get tunnelid "$cfg" tunnelid
+
+			local username
+			config_get username "$cfg" username
+
+			local password
+			config_get password "$cfg" password
+
+			uci_set_state network "$cfg" ipaddr "$wanip"
+
+			[ -n "$tunnelid" ] && [ -n "$username" ] && [ -n "$password" ] && {
+				[ "${#password}" == 32 -a -z "${password//[a-fA-F0-9]/}" ] || {
+					password="$(echo -n "$password" | md5sum)"; password="${password%% *}"
+				}
+
+				(
+					local url="http://ipv4.tunnelbroker.net/ipv4_end.php?ip=AUTO&apikey=$username&pass=$password&tid=$tunnelid"
+					local try=0
+					local max=3
+
+					while [ $((++try)) -le $max ]; do
+						wget -qO/dev/null "$url" 2>/dev/null && {
+							logger -t 6in4-update "Updated tunnel #$tunnelid endpoint to $wanip"
+							ifup "$cfg"
+							break
+						} || {
+							logger -t 6in4-update "Try $try/$max failed, retrying"
+							sleep 1
+						}
+					done
+				)&
+			} || {
+				logger -t 6in4-update "Re-establishing tunnel due to change on $INTERFACE ($DEVICE)"
+				ifup "$cfg" &
+			}
+		}
+	}
+
+	config_foreach update_tunnel interface
+fi
diff --git a/package/6in4/files.old/6in4.sh b/package/6in4/files.old/6in4.sh
new file mode 100755
index 0000000000..5f8dfffe57
--- /dev/null
+++ b/package/6in4/files.old/6in4.sh
@@ -0,0 +1,104 @@
+# 6in4.sh - IPv6-in-IPv4 tunnel backend
+# Copyright (c) 2010 OpenWrt.org
+
+find_6in4_wanif() {
+	local if=$(ip -4 r l e 0.0.0.0/0); if="${if#default* dev }"; if="${if%% *}"
+	[ -n "$if" ] && grep -qs "^ *$if:" /proc/net/dev && echo "$if"
+}
+
+find_6in4_wanip() {
+	local ip=$(ip -4 a s dev "$1"); ip="${ip#*inet }"
+	echo "${ip%%[^0-9.]*}"
+}
+
+# Hook into scan_interfaces() to synthesize a .device option
+# This is needed for /sbin/ifup to properly dispatch control
+# to setup_interface_6in4() even if no .ifname is set in
+# the configuration.
+scan_6in4() {
+	config_set "$1" device "6in4-$1"
+}
+
+coldplug_interface_6in4() {
+	setup_interface_6in4 "6in4-$1" "$1"
+}
+
+setup_interface_6in4() {
+	local iface="$1"
+	local cfg="$2"
+	local link="6in4-$cfg"
+
+	local local4=$(uci_get network "$cfg" ipaddr)
+
+	local remote4
+	config_get remote4 "$cfg" peeraddr
+
+	local local6
+	config_get local6 "$cfg" ip6addr
+
+	local mtu
+	config_get mtu "$cfg" mtu
+
+	local ttl
+	config_get ttl "$cfg" ttl
+
+	local metric
+	config_get metric "$cfg" metric
+
+	local defaultroute
+	config_get_bool defaultroute "$cfg" defaultroute 1
+
+	# If local4 is unset, guess local IPv4 address from the
+	# interface used by the default route.
+	[ -z "$local4" ] && {
+		local wanif=$(find_6in4_wanif)
+		[ -n "$wanif" ] && {
+			local4=$(find_6in4_wanip "$wanif")
+			uci_set_state network "$cfg" wan_device "$wanif"
+		}
+	}
+
+	[ -n "$local4" ] && {
+		# creating the tunnel below will trigger a net subsystem event
+		# prevent it from touching or iface by disabling .auto here
+		uci_set_state network "$cfg" ifname $link
+		uci_set_state network "$cfg" auto 0
+
+		ip tunnel add $link mode sit remote $remote4 local $local4 ttl ${ttl:-64}
+		ip link set $link up
+		ip link set mtu ${mtu:-1280} dev $link
+		ip addr add $local6 dev $link
+
+		uci_set_state network "$cfg" ipaddr $local4
+		uci_set_state network "$cfg" ip6addr $local6
+
+		[ "$defaultroute" = 1 ] && {
+			ip -6 route add ::/0 ${metric:+metric $metric} dev $link
+			uci_set_state network "$cfg" defaultroute 1
+		}
+
+		env -i ACTION="ifup" INTERFACE="$cfg" DEVICE="$link" PROTO=6in4 /sbin/hotplug-call "iface" &
+	} || {
+		echo "Cannot determine local IPv4 address for 6in4 tunnel $cfg - skipping"
+	}
+}
+
+stop_interface_6in4() {
+	local cfg="$1"
+	local link="6in4-$cfg"
+
+	local local6=$(uci_get_state network "$cfg" ip6addr)
+	local defaultroute=$(uci_get_state network "$cfg" defaultroute)
+
+	grep -qs "^ *$link:" /proc/net/dev && {
+		env -i ACTION="ifdown" INTERFACE="$cfg" DEVICE="$link" PROTO=6in4 /sbin/hotplug-call "iface" &
+
+		[ "$defaultroute" = "1" ] && {
+			ip -6 route del ::/0 dev $link
+		}
+
+		ip addr del $local6 dev $link
+		ip link set $link down
+		ip tunnel del $link
+	}
+}
diff --git a/package/6in4/files/6in4.hotplug b/package/6in4/files/6in4.hotplug
index 3d9def448e..8d78555477 100644
--- a/package/6in4/files/6in4.hotplug
+++ b/package/6in4/files/6in4.hotplug
@@ -3,6 +3,9 @@
 if [ "$ACTION" = ifup ]; then
 	. /etc/functions.sh
 
+	INCLUDE_ONLY=1
+	. /lib/netifd/proto/6in4.sh
+
 	include /lib/network
 	scan_interfaces
 
@@ -19,49 +22,7 @@ if [ "$ACTION" = ifup ]; then
 
 		local wanip=$(find_6in4_wanip "$wandev")
 
-		[ -n "$wanip" ] && {
-			lsmod | grep -q ^sit || {
-				logger -t 6in4-update "Tunneling driver not loaded yet, deferring action"
-				exit 0
-			}
-
-			local tunnelid
-			config_get tunnelid "$cfg" tunnelid
-
-			local username
-			config_get username "$cfg" username
-
-			local password
-			config_get password "$cfg" password
-
-			uci_set_state network "$cfg" ipaddr "$wanip"
-
-			[ -n "$tunnelid" ] && [ -n "$username" ] && [ -n "$password" ] && {
-				[ "${#password}" == 32 -a -z "${password//[a-fA-F0-9]/}" ] || {
-					password="$(echo -n "$password" | md5sum)"; password="${password%% *}"
-				}
-
-				(
-					local url="http://ipv4.tunnelbroker.net/ipv4_end.php?ip=AUTO&apikey=$username&pass=$password&tid=$tunnelid"
-					local try=0
-					local max=3
-
-					while [ $((++try)) -le $max ]; do
-						wget -qO/dev/null "$url" 2>/dev/null && {
-							logger -t 6in4-update "Updated tunnel #$tunnelid endpoint to $wanip"
-							ifup "$cfg"
-							break
-						} || {
-							logger -t 6in4-update "Try $try/$max failed, retrying"
-							sleep 1
-						}
-					done
-				)&
-			} || {
-				logger -t 6in4-update "Re-establishing tunnel due to change on $INTERFACE ($DEVICE)"
-				ifup "$cfg" &
-			}
-		}
+		[ -n "$wanip" ] && ifup "$cfg"
 	}
 
 	config_foreach update_tunnel interface
diff --git a/package/6in4/files/6in4.sh b/package/6in4/files/6in4.sh
index 5f8dfffe57..14748ebd10 100755
--- a/package/6in4/files/6in4.sh
+++ b/package/6in4/files/6in4.sh
@@ -1,6 +1,13 @@
+#!/bin/sh
 # 6in4.sh - IPv6-in-IPv4 tunnel backend
 # Copyright (c) 2010 OpenWrt.org
 
+[ -n "$INCLUDE_ONLY" ] || {
+	. /etc/functions.sh
+	. ../netifd-proto.sh
+	init_proto "$@"
+}
+
 find_6in4_wanif() {
 	local if=$(ip -4 r l e 0.0.0.0/0); if="${if#default* dev }"; if="${if%% *}"
 	[ -n "$if" ] && grep -qs "^ *$if:" /proc/net/dev && echo "$if"
@@ -23,82 +30,109 @@ coldplug_interface_6in4() {
 	setup_interface_6in4 "6in4-$1" "$1"
 }
 
-setup_interface_6in4() {
-	local iface="$1"
-	local cfg="$2"
-	local link="6in4-$cfg"
 
-	local local4=$(uci_get network "$cfg" ipaddr)
+tun_error() {
+	local cfg="$1"; shift;
 
-	local remote4
-	config_get remote4 "$cfg" peeraddr
+	[ -n "$1" ] && proto_notify_error "$cfg" "$@"
+	proto_block_restart "$cfg"
+}
 
-	local local6
-	config_get local6 "$cfg" ip6addr
+proto_6in4_setup() {
+	local cfg="$1"
+	local iface="$2"
+	local link="6in4-$cfg"
 
-	local mtu
-	config_get mtu "$cfg" mtu
+	json_get_var mtu mtu
+	json_get_var ttl ttl
+	json_get_var local4 ipaddr
+	json_get_var remote4 peeraddr
+	json_get_var ip6addr ip6addr
+	json_get_var tunnelid tunnelid
+	json_get_var username username
+	json_get_var password password
+
+	[ -z "$ip6addr" -o -z "$remote4" ] && {
+		tun_error "$cfg" "MISSING_ADDRESS"
+		return
+	}
 
-	local ttl
-	config_get ttl "$cfg" ttl
+	[ -z "$local4" ] && {
+		local wanif=$(find_6in4_wanif)
+		[ -z "$wanif" ] && {
+			tun_error "$cfg" "NO_WAN_LINK"
+			return
+		}
 
-	local metric
-	config_get metric "$cfg" metric
+		. /lib/network/config.sh
+		local wancfg="$(find_config "$wanif")"
+		[ -z "$wancfg" ] && {
+			tun_error "$cfg" "NO_WAN_LINK"
+			return
+		}
 
-	local defaultroute
-	config_get_bool defaultroute "$cfg" defaultroute 1
+		# If local4 is unset, guess local IPv4 address from the
+		# interface used by the default route.
+		[ -n "$wanif" ] && local4=$(find_6in4_wanip "$wanif")
 
-	# If local4 is unset, guess local IPv4 address from the
-	# interface used by the default route.
-	[ -z "$local4" ] && {
-		local wanif=$(find_6in4_wanif)
-		[ -n "$wanif" ] && {
-			local4=$(find_6in4_wanip "$wanif")
-			uci_set_state network "$cfg" wan_device "$wanif"
+		[ -z "$local4" ] && {
+			tun_error "$cfg" "NO_WAN_LINK"
+			return
 		}
 	}
 
-	[ -n "$local4" ] && {
-		# creating the tunnel below will trigger a net subsystem event
-		# prevent it from touching or iface by disabling .auto here
-		uci_set_state network "$cfg" ifname $link
-		uci_set_state network "$cfg" auto 0
+	local local6="${ip6addr%%/*}"
+	local mask6="${ip6addr##*/}"
+	[[ "$local6" = "$mask6" ]] && mask6=
+
+	proto_init_update "$link" 1
+	proto_add_ipv6_address "$local6" "$mask6"
+	proto_add_ipv6_route "::" 0
 
-		ip tunnel add $link mode sit remote $remote4 local $local4 ttl ${ttl:-64}
-		ip link set $link up
-		ip link set mtu ${mtu:-1280} dev $link
-		ip addr add $local6 dev $link
+	proto_add_tunnel
+	json_add_string mode sit
+	json_add_int mtu "${mtu:-1280}"
+	json_add_int ttl "${ttl:-64}"
+	json_add_string local "$local4"
+	json_add_string remote "$remote4"
+	proto_close_tunnel
 
-		uci_set_state network "$cfg" ipaddr $local4
-		uci_set_state network "$cfg" ip6addr $local6
+	proto_send_update "$cfg"
 
-		[ "$defaultroute" = 1 ] && {
-			ip -6 route add ::/0 ${metric:+metric $metric} dev $link
-			uci_set_state network "$cfg" defaultroute 1
+	[ -n "$tunnelid" -a -n "$username" -a -n "$password" ] && {
+		[ "${#password}" == 32 -a -z "${password//[a-fA-F0-9]/}" ] || {
+			password="$(echo -n "$password" | md5sum)"; password="${password%% *}"
 		}
 
-		env -i ACTION="ifup" INTERFACE="$cfg" DEVICE="$link" PROTO=6in4 /sbin/hotplug-call "iface" &
-	} || {
-		echo "Cannot determine local IPv4 address for 6in4 tunnel $cfg - skipping"
+		local url="http://ipv4.tunnelbroker.net/ipv4_end.php?ip=AUTO&apikey=$username&pass=$password&tid=$tunnelid"
+		local try=0
+		local max=3
+
+		while [ $((++try)) -le $max ]; do
+			wget -qO/dev/null "$url" 2>/dev/null && break
+			sleep 1
+		done
 	}
 }
 
-stop_interface_6in4() {
+proto_6in4_teardown() {
 	local cfg="$1"
-	local link="6in4-$cfg"
-
-	local local6=$(uci_get_state network "$cfg" ip6addr)
-	local defaultroute=$(uci_get_state network "$cfg" defaultroute)
-
-	grep -qs "^ *$link:" /proc/net/dev && {
-		env -i ACTION="ifdown" INTERFACE="$cfg" DEVICE="$link" PROTO=6in4 /sbin/hotplug-call "iface" &
+}
 
-		[ "$defaultroute" = "1" ] && {
-			ip -6 route del ::/0 dev $link
-		}
+proto_6in4_init_config() {
+	no_device=1             
+	available=1
+
+	proto_config_add_string "ipaddr"
+	proto_config_add_string "ip6addr"
+	proto_config_add_string "peeraddr"
+	proto_config_add_string "tunnelid"
+	proto_config_add_string "username"
+	proto_config_add_string "password"
+	proto_config_add_int "mtu"
+	proto_config_add_int "ttl"
+}
 
-		ip addr del $local6 dev $link
-		ip link set $link down
-		ip tunnel del $link
-	}
+[ -n "$INCLUDE_ONLY" ] || {
+	add_protocol 6in4
 }
-- 
2.30.2