scripts: reorganize directory layout
authorFelix Fietkau <nbd@openwrt.org>
Tue, 24 Sep 2013 07:35:22 +0000 (09:35 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 19 Oct 2013 15:31:55 +0000 (17:31 +0200)
move example scripts from dummy/ to examples/
keep scripts that can be used as-is in scripts/

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
dummy/netifd-proto.sh [deleted file]
dummy/proto/ppp.sh [deleted file]
dummy/proto/pptp.sh [deleted file]
examples/hotplug-cmd [new file with mode: 0755]
examples/proto/ppp.sh [new file with mode: 0755]
examples/proto/pptp.sh [new file with mode: 0755]
netifd.h
scripts/hotplug-cmd [deleted file]
scripts/netifd-proto.sh [new file with mode: 0755]

diff --git a/dummy/netifd-proto.sh b/dummy/netifd-proto.sh
deleted file mode 100755 (executable)
index 6f20de9..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-. /usr/share/libubox/jshn.sh
-
-append() {
-       local var="$1"
-       local value="$2"
-       local sep="${3:- }"
-
-       eval "export -- \"$var=\${$var:+\${$var}\${value:+\$sep}}\$value\""
-}
-
-proto_config_add_generic() {
-       json_add_array ""
-       json_add_string "" "$1"
-       json_add_int "" "$2"
-       json_close_array
-}
-
-proto_config_add_int() {
-       proto_config_add_generic "$1" 5
-}
-
-proto_config_add_string() {
-       proto_config_add_generic "$1" 3
-}
-
-proto_config_add_boolean() {
-       proto_config_add_generic "$1" 7
-}
-
-add_default_handler() {
-       case "$(type $1 2>/dev/null)" in
-               *function*) return;;
-               *) eval "$1() { return; }"
-       esac
-}
-
-_proto_do_teardown() {
-       json_load "$data"
-       eval "proto_$1_teardown \"$interface\" \"$ifname\""
-}
-
-_proto_do_setup() {
-       json_load "$data"
-       _EXPORT_VAR=0
-       _EXPORT_VARS=
-       eval "proto_$1_setup \"$interface\" \"$ifname\""
-}
-
-proto_init_update() {
-       local ifname="$1"
-       local up="$2"
-       local external="$3"
-
-       PROTO_KEEP=0
-       PROTO_INIT=1
-       PROTO_TUNNEL_OPEN=
-       PROTO_IPADDR=
-       PROTO_IP6ADDR=
-       PROTO_ROUTE=
-       PROTO_ROUTE6=
-       PROTO_PREFIX6=
-       PROTO_DNS=
-       PROTO_DNS_SEARCH=
-       json_init
-       json_add_int action 0
-       [ -n "$ifname" -a "*" != "$ifname" ] && json_add_string "ifname" "$ifname"
-       json_add_boolean "link-up" "$up"
-       [ -n "$3" ] && json_add_boolean "address-external" "$external"
-}
-
-proto_set_keep() {
-       PROTO_KEEP="$1"
-}
-
-proto_close_nested() {
-       [ -n "$PROTO_NESTED_OPEN" ] && json_close_object
-       PROTO_NESTED_OPEN=
-}
-
-proto_add_nested() {
-       PROTO_NESTED_OPEN=1
-       json_add_object "$1"
-}
-
-proto_add_tunnel() {
-       proto_add_nested "tunnel"
-}
-
-proto_close_tunnel() {
-       proto_close_nested
-}
-
-proto_add_data() {
-       proto_add_nested "data"
-}
-
-proto_close_data() {
-       proto_close_nested
-}
-
-proto_add_dns_server() {
-       local address="$1"
-
-       append PROTO_DNS "$address"
-}
-
-proto_add_dns_search() {
-       local address="$1"
-
-       append PROTO_DNS_SEARCH "$address"
-}
-
-proto_add_ipv4_address() {
-       local address="$1"
-       local mask="$2"
-       local broadcast="$3"
-       local ptp="$4"
-
-       append PROTO_IPADDR "$address/$mask/$broadcast/$ptp"
-}
-
-proto_add_ipv6_address() {
-       local address="$1"
-       local mask="$2"
-       local preferred="$3"
-       local valid="$4"
-       local offlink="$5"
-
-       append PROTO_IP6ADDR "$address/$mask/$preferred/$valid/$offlink"
-}
-
-proto_add_ipv4_route() {
-       local target="$1"
-       local mask="$2"
-       local gw="$3"
-
-       append PROTO_ROUTE "$target/$mask/$gw//"
-}
-
-proto_add_ipv6_route() {
-       local target="$1"
-       local mask="$2"
-       local gw="$3"
-       local metric="$4"
-       local valid="$5"
-       local source="$6"
-
-       append PROTO_ROUTE6 "$target/$mask/$gw/$metric/$valid/$source"
-}
-
-proto_add_ipv6_prefix() {
-       local prefix="$1"
-       local valid="$2"
-       local preferred="$3"
-
-       if [ -z "$valid" ]; then
-               append PROTO_PREFIX6 "$prefix"
-       else
-               [ -z "$preferred" ] && preferred="$valid"
-               append PROTO_PREFIX6 "$prefix,$valid,$preferred"
-       fi
-}
-
-_proto_push_ipv4_addr() {
-       local str="$1"
-       local address mask broadcast ptp
-
-       address="${str%%/*}"
-       str="${str#*/}"
-       mask="${str%%/*}"
-       str="${str#*/}"
-       broadcast="${str%%/*}"
-       str="${str#*/}"
-       ptp="$str"
-
-       json_add_object ""
-       json_add_string ipaddr "$address"
-       [ -n "$mask" ] && json_add_string mask "$mask"
-       [ -n "$broadcast" ] && json_add_string broadcast "$broadcast"
-       [ -n "$ptp" ] && json_add_string ptp "$ptp"
-       json_close_object
-}
-
-_proto_push_ipv6_addr() {
-       local str="$1"
-       local address mask preferred valid offlink
-
-       address="${str%%/*}"
-       str="${str#*/}"
-       mask="${str%%/*}"
-       str="${str#*/}"
-       preferred="${str%%/*}"
-       str="${str#*/}"
-       valid="${str%%/*}"
-       str="${str#*/}"
-       offlink="${str%%/*}"
-
-       json_add_object ""
-       json_add_string ipaddr "$address"
-       [ -n "$mask" ] && json_add_string mask "$mask"
-       [ -n "$preferred" ] && json_add_int preferred "$preferred"
-       [ -n "$valid" ] && json_add_int valid "$valid"
-       [ -n "$offlink" ] && json_add_boolean offlink "$offlink"
-       json_close_object
-}
-
-_proto_push_string() {
-       json_add_string "" "$1"
-}
-
-_proto_push_route() {
-       local str="$1";
-       local target="${str%%/*}"
-       str="${str#*/}"
-       local mask="${str%%/*}"
-       str="${str#*/}"
-       local gw="${str%%/*}"
-       str="${str#*/}"
-       local metric="${str%%/*}"
-       str="${str#*/}"
-       local valid="${str%%/*}"
-       str="${str#*/}"
-       local source="${str}"
-
-       json_add_object ""
-       json_add_string target "$target"
-       json_add_string netmask "$mask"
-       [ -n "$gw" ] && json_add_string gateway "$gw"
-       [ -n "$metric" ] && json_add_int metric "$metric"
-       [ -n "$valid" ] && json_add_int valid "$valid"
-       [ -n "$source" ] && json_add_string source "$source"
-       json_close_object
-}
-
-_proto_push_array() {
-       local name="$1"
-       local val="$2"
-       local cb="$3"
-
-       [ -n "$val" ] || return 0
-       json_add_array "$name"
-       for item in $val; do
-               eval "$cb \"\$item\""
-       done
-       json_close_array
-}
-
-_proto_notify() {
-       local interface="$1"
-       local options="$2"
-       json_add_string "interface" "$interface"
-       ubus $options call network.interface notify_proto "$(json_dump)"
-}
-
-proto_send_update() {
-       local interface="$1"
-
-       proto_close_nested
-       json_add_boolean keep "$PROTO_KEEP"
-       _proto_push_array "ipaddr" "$PROTO_IPADDR" _proto_push_ipv4_addr
-       _proto_push_array "ip6addr" "$PROTO_IP6ADDR" _proto_push_ipv6_addr
-       _proto_push_array "routes" "$PROTO_ROUTE" _proto_push_route
-       _proto_push_array "routes6" "$PROTO_ROUTE6" _proto_push_route
-       _proto_push_array "ip6prefix" "$PROTO_PREFIX6" _proto_push_string
-       _proto_push_array "dns" "$PROTO_DNS" _proto_push_string
-       _proto_push_array "dns_search" "$PROTO_DNS_SEARCH" _proto_push_string
-       _proto_notify "$interface"
-}
-
-proto_export() {
-       local var="VAR${_EXPORT_VAR}"
-       _EXPORT_VAR="$(($_EXPORT_VAR + 1))"
-       export -- "$var=$1"
-       append _EXPORT_VARS "$var"
-}
-
-proto_run_command() {
-       local interface="$1"; shift
-
-       json_init
-       json_add_int action 1
-       json_add_array command
-       while [ $# -gt 0 ]; do
-               json_add_string "" "$1"
-               shift
-       done
-       json_close_array
-       [ -n "$_EXPORT_VARS" ] && {
-               json_add_array env
-               for var in $_EXPORT_VARS; do
-                       eval "json_add_string \"\" \"\${$var}\""
-               done
-               json_close_array
-       }
-       _proto_notify "$interface"
-}
-
-proto_kill_command() {
-       local interface="$1"; shift
-
-       json_init
-       json_add_int action 2
-       [ -n "$1" ] && json_add_int signal "$1"
-       _proto_notify "$interface"
-}
-
-proto_notify_error() {
-       local interface="$1"; shift
-
-       json_init
-       json_add_int action 3
-       json_add_array error
-       while [ $# -gt 0 ]; do
-               json_add_string "" "$1"
-               shift
-       done
-       json_close_array
-       _proto_notify "$interface"
-}
-
-proto_block_restart() {
-       local interface="$1"; shift
-
-       json_init
-       json_add_int action 4
-       _proto_notify "$interface"
-}
-
-proto_set_available() {
-       local interface="$1"
-       local state="$2"
-       json_init
-       json_add_int action 5
-       json_add_boolean available "$state"
-       _proto_notify "$interface"
-}
-
-proto_add_host_dependency() {
-       local interface="$1"
-       local host="$2"
-       local ifname="$3"
-
-       # execute in subshell to not taint callers env
-       # see tickets #11046, #11545, #11570
-       (
-               json_init
-               json_add_int action 6
-               json_add_string host "$host"
-               [ -n "$ifname" ] && json_add_string ifname "$ifname"
-               _proto_notify "$interface" -S
-       )
-}
-
-proto_setup_failed() {
-       local interface="$1"
-       json_init
-       json_add_int action 7
-       _proto_notify "$interface"
-}
-
-init_proto() {
-       proto="$1"; shift
-       cmd="$1"; shift
-
-       case "$cmd" in
-               dump)
-                       add_protocol() {
-                               no_device=0
-                               available=0
-
-                               add_default_handler "proto_$1_init_config"
-
-                               json_init
-                               json_add_string "name" "$1"
-                               json_add_array "config"
-                               eval "proto_$1_init_config"
-                               json_close_array
-                               json_add_boolean no-device "$no_device"
-                               json_add_boolean available "$available"
-                               json_dump
-                       }
-               ;;
-               setup|teardown)
-                       interface="$1"; shift
-                       data="$1"; shift
-                       ifname="$1"; shift
-
-                       add_protocol() {
-                               [[ "$proto" == "$1" ]] || return 0
-
-                               case "$cmd" in
-                                       setup) _proto_do_setup "$1";;
-                                       teardown) _proto_do_teardown "$1" ;;
-                                       *) return 1 ;;
-                               esac
-                       }
-               ;;
-       esac
-}
diff --git a/dummy/proto/ppp.sh b/dummy/proto/ppp.sh
deleted file mode 100755 (executable)
index c710bf2..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/sh
-
-. ../netifd-proto.sh
-init_proto "$@"
-
-ppp_generic_init_config() {
-       proto_config_add_string "username"
-       proto_config_add_string "password"
-       proto_config_add_int "keepalive"
-}
-
-proto_ppp_init_config() {
-       no_device=1
-       available=1
-       ppp_generic_init_config
-}
-
-proto_ppp_setup() {
-       echo "ppp_setup($1): $2"
-}
-
-proto_ppp_teardown() {
-       return
-}
-
-add_protocol ppp
-
-proto_pppoe_init_config() {
-       ppp_generic_init_config
-}
-
-proto_pppoe_setup() {
-       local interface="$1"
-       local device="$2"
-
-       json_get_var username username
-       json_get_var password password
-       echo "pppoe_setup($interface, $device), username=$username, password=$password"
-       proto_init_update pppoe-$interface 1
-       proto_set_keep 1
-       proto_add_ipv4_address "192.168.2.1" 32
-       proto_add_dns_server "192.168.2.2"
-       proto_add_ipv4_route "0.0.0.0" 0 192.168.2.2
-       proto_add_data
-       json_add_string "ppp-type" "pppoe"
-       proto_close_data
-       proto_send_update "$interface"
-
-       proto_init_update pppoe-$interface 1
-       proto_set_keep 1
-       proto_add_ipv6_address "fe80::2" 64
-       proto_add_ipv6_route "::0" 0 "fe80::1"
-       proto_add_data
-       json_add_string "ppp-type" "pppoe"
-       proto_close_data
-       proto_send_update "$interface"
-
-       proto_run_command "$interface" sleep 30
-}
-
-proto_pppoe_teardown() {
-       [ "$ERROR" = 9 ] && {
-               proto_notify_error "$interface" PROCESS_KILLED
-               proto_block_restart "$interface"
-       }
-       proto_kill_command "$interface"
-       return
-}
-
-add_protocol pppoe
diff --git a/dummy/proto/pptp.sh b/dummy/proto/pptp.sh
deleted file mode 100755 (executable)
index 914604f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/sh
-
-. ../netifd-proto.sh
-init_proto "$@"
-
-proto_pptp_init_config() {
-       no_device=1
-       available=1
-
-       proto_config_add_string "username"
-       proto_config_add_string "password"
-       proto_config_add_string server
-}
-
-proto_pptp_setup() {
-       local interface="$1"
-       local device="$2"
-
-       json_get_var server server
-       proto_add_host_dependency "$interface" "$server"
-
-       json_get_var username username
-       json_get_var password password
-       echo "pptp_setup($interface), username=$username, password=$password"
-       proto_init_update "pptp-$interface" 1
-       proto_set_keep 1
-       proto_add_ipv4_address "192.168.9.1" 32
-       proto_add_dns_server "192.168.9.2"
-       proto_add_ipv4_route "0.0.0.0" 0 192.168.9.2
-       proto_add_data
-       json_add_string "ppp-type" "pptp"
-       proto_close_data
-       proto_send_update "$interface"
-
-       proto_run_command "$interface" sleep 30
-}
-
-proto_pptp_teardown() {
-       return
-}
-
-add_protocol pptp
-
diff --git a/examples/hotplug-cmd b/examples/hotplug-cmd
new file mode 100755 (executable)
index 0000000..2488a77
--- /dev/null
@@ -0,0 +1 @@
+echo "Action: $ACTION, Interface: $INTERFACE"
diff --git a/examples/proto/ppp.sh b/examples/proto/ppp.sh
new file mode 100755 (executable)
index 0000000..f0d0ca3
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/sh
+DUMMY=1
+. ../../scripts/netifd-proto.sh
+
+init_proto "$@"
+
+ppp_generic_init_config() {
+       proto_config_add_string "username"
+       proto_config_add_string "password"
+       proto_config_add_int "keepalive"
+}
+
+proto_ppp_init_config() {
+       no_device=1
+       available=1
+       ppp_generic_init_config
+}
+
+proto_ppp_setup() {
+       echo "ppp_setup($1): $2"
+}
+
+proto_ppp_teardown() {
+       return
+}
+
+add_protocol ppp
+
+proto_pppoe_init_config() {
+       ppp_generic_init_config
+}
+
+proto_pppoe_setup() {
+       local interface="$1"
+       local device="$2"
+
+       json_get_var username username
+       json_get_var password password
+       echo "pppoe_setup($interface, $device), username=$username, password=$password"
+       proto_init_update pppoe-$interface 1
+       proto_set_keep 1
+       proto_add_ipv4_address "192.168.2.1" 32
+       proto_add_dns_server "192.168.2.2"
+       proto_add_ipv4_route "0.0.0.0" 0 192.168.2.2
+       proto_add_data
+       json_add_string "ppp-type" "pppoe"
+       proto_close_data
+       proto_send_update "$interface"
+
+       proto_init_update pppoe-$interface 1
+       proto_set_keep 1
+       proto_add_ipv6_address "fe80::2" 64
+       proto_add_ipv6_route "::0" 0 "fe80::1"
+       proto_add_data
+       json_add_string "ppp-type" "pppoe"
+       proto_close_data
+       proto_send_update "$interface"
+
+       proto_run_command "$interface" sleep 30
+}
+
+proto_pppoe_teardown() {
+       [ "$ERROR" = 9 ] && {
+               proto_notify_error "$interface" PROCESS_KILLED
+               proto_block_restart "$interface"
+       }
+       proto_kill_command "$interface"
+       return
+}
+
+add_protocol pppoe
diff --git a/examples/proto/pptp.sh b/examples/proto/pptp.sh
new file mode 100755 (executable)
index 0000000..5189e95
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/sh
+. ../../scripts/netifd-proto.sh
+init_proto "$@"
+
+proto_pptp_init_config() {
+       no_device=1
+       available=1
+
+       proto_config_add_string "username"
+       proto_config_add_string "password"
+       proto_config_add_string server
+}
+
+proto_pptp_setup() {
+       local interface="$1"
+       local device="$2"
+
+       json_get_var server server
+       proto_add_host_dependency "$interface" "$server"
+
+       json_get_var username username
+       json_get_var password password
+       echo "pptp_setup($interface), username=$username, password=$password"
+       proto_init_update "pptp-$interface" 1
+       proto_set_keep 1
+       proto_add_ipv4_address "192.168.9.1" 32
+       proto_add_dns_server "192.168.9.2"
+       proto_add_ipv4_route "0.0.0.0" 0 192.168.9.2
+       proto_add_data
+       json_add_string "ppp-type" "pptp"
+       proto_close_data
+       proto_send_update "$interface"
+
+       proto_run_command "$interface" sleep 30
+}
+
+proto_pptp_teardown() {
+       return
+}
+
+add_protocol pptp
+
index befa2ccb331985e11f18c62d2726a8d1843fe1c7..1f64555d46f638712394f9049a6b810334d12169 100644 (file)
--- a/netifd.h
+++ b/netifd.h
@@ -29,8 +29,8 @@
 #include "utils.h"
 
 #ifdef DUMMY_MODE
-#define DEFAULT_MAIN_PATH      "./dummy"
-#define DEFAULT_HOTPLUG_PATH   "./scripts/hotplug-cmd"
+#define DEFAULT_MAIN_PATH      "./examples"
+#define DEFAULT_HOTPLUG_PATH   "./examples/hotplug-cmd"
 #define DEFAULT_RESOLV_CONF    "./tmp/resolv.conf"
 #else
 #define DEFAULT_MAIN_PATH      "/lib/netifd"
diff --git a/scripts/hotplug-cmd b/scripts/hotplug-cmd
deleted file mode 100755 (executable)
index 2488a77..0000000
+++ /dev/null
@@ -1 +0,0 @@
-echo "Action: $ACTION, Interface: $INTERFACE"
diff --git a/scripts/netifd-proto.sh b/scripts/netifd-proto.sh
new file mode 100755 (executable)
index 0000000..6f20de9
--- /dev/null
@@ -0,0 +1,399 @@
+. /usr/share/libubox/jshn.sh
+
+append() {
+       local var="$1"
+       local value="$2"
+       local sep="${3:- }"
+
+       eval "export -- \"$var=\${$var:+\${$var}\${value:+\$sep}}\$value\""
+}
+
+proto_config_add_generic() {
+       json_add_array ""
+       json_add_string "" "$1"
+       json_add_int "" "$2"
+       json_close_array
+}
+
+proto_config_add_int() {
+       proto_config_add_generic "$1" 5
+}
+
+proto_config_add_string() {
+       proto_config_add_generic "$1" 3
+}
+
+proto_config_add_boolean() {
+       proto_config_add_generic "$1" 7
+}
+
+add_default_handler() {
+       case "$(type $1 2>/dev/null)" in
+               *function*) return;;
+               *) eval "$1() { return; }"
+       esac
+}
+
+_proto_do_teardown() {
+       json_load "$data"
+       eval "proto_$1_teardown \"$interface\" \"$ifname\""
+}
+
+_proto_do_setup() {
+       json_load "$data"
+       _EXPORT_VAR=0
+       _EXPORT_VARS=
+       eval "proto_$1_setup \"$interface\" \"$ifname\""
+}
+
+proto_init_update() {
+       local ifname="$1"
+       local up="$2"
+       local external="$3"
+
+       PROTO_KEEP=0
+       PROTO_INIT=1
+       PROTO_TUNNEL_OPEN=
+       PROTO_IPADDR=
+       PROTO_IP6ADDR=
+       PROTO_ROUTE=
+       PROTO_ROUTE6=
+       PROTO_PREFIX6=
+       PROTO_DNS=
+       PROTO_DNS_SEARCH=
+       json_init
+       json_add_int action 0
+       [ -n "$ifname" -a "*" != "$ifname" ] && json_add_string "ifname" "$ifname"
+       json_add_boolean "link-up" "$up"
+       [ -n "$3" ] && json_add_boolean "address-external" "$external"
+}
+
+proto_set_keep() {
+       PROTO_KEEP="$1"
+}
+
+proto_close_nested() {
+       [ -n "$PROTO_NESTED_OPEN" ] && json_close_object
+       PROTO_NESTED_OPEN=
+}
+
+proto_add_nested() {
+       PROTO_NESTED_OPEN=1
+       json_add_object "$1"
+}
+
+proto_add_tunnel() {
+       proto_add_nested "tunnel"
+}
+
+proto_close_tunnel() {
+       proto_close_nested
+}
+
+proto_add_data() {
+       proto_add_nested "data"
+}
+
+proto_close_data() {
+       proto_close_nested
+}
+
+proto_add_dns_server() {
+       local address="$1"
+
+       append PROTO_DNS "$address"
+}
+
+proto_add_dns_search() {
+       local address="$1"
+
+       append PROTO_DNS_SEARCH "$address"
+}
+
+proto_add_ipv4_address() {
+       local address="$1"
+       local mask="$2"
+       local broadcast="$3"
+       local ptp="$4"
+
+       append PROTO_IPADDR "$address/$mask/$broadcast/$ptp"
+}
+
+proto_add_ipv6_address() {
+       local address="$1"
+       local mask="$2"
+       local preferred="$3"
+       local valid="$4"
+       local offlink="$5"
+
+       append PROTO_IP6ADDR "$address/$mask/$preferred/$valid/$offlink"
+}
+
+proto_add_ipv4_route() {
+       local target="$1"
+       local mask="$2"
+       local gw="$3"
+
+       append PROTO_ROUTE "$target/$mask/$gw//"
+}
+
+proto_add_ipv6_route() {
+       local target="$1"
+       local mask="$2"
+       local gw="$3"
+       local metric="$4"
+       local valid="$5"
+       local source="$6"
+
+       append PROTO_ROUTE6 "$target/$mask/$gw/$metric/$valid/$source"
+}
+
+proto_add_ipv6_prefix() {
+       local prefix="$1"
+       local valid="$2"
+       local preferred="$3"
+
+       if [ -z "$valid" ]; then
+               append PROTO_PREFIX6 "$prefix"
+       else
+               [ -z "$preferred" ] && preferred="$valid"
+               append PROTO_PREFIX6 "$prefix,$valid,$preferred"
+       fi
+}
+
+_proto_push_ipv4_addr() {
+       local str="$1"
+       local address mask broadcast ptp
+
+       address="${str%%/*}"
+       str="${str#*/}"
+       mask="${str%%/*}"
+       str="${str#*/}"
+       broadcast="${str%%/*}"
+       str="${str#*/}"
+       ptp="$str"
+
+       json_add_object ""
+       json_add_string ipaddr "$address"
+       [ -n "$mask" ] && json_add_string mask "$mask"
+       [ -n "$broadcast" ] && json_add_string broadcast "$broadcast"
+       [ -n "$ptp" ] && json_add_string ptp "$ptp"
+       json_close_object
+}
+
+_proto_push_ipv6_addr() {
+       local str="$1"
+       local address mask preferred valid offlink
+
+       address="${str%%/*}"
+       str="${str#*/}"
+       mask="${str%%/*}"
+       str="${str#*/}"
+       preferred="${str%%/*}"
+       str="${str#*/}"
+       valid="${str%%/*}"
+       str="${str#*/}"
+       offlink="${str%%/*}"
+
+       json_add_object ""
+       json_add_string ipaddr "$address"
+       [ -n "$mask" ] && json_add_string mask "$mask"
+       [ -n "$preferred" ] && json_add_int preferred "$preferred"
+       [ -n "$valid" ] && json_add_int valid "$valid"
+       [ -n "$offlink" ] && json_add_boolean offlink "$offlink"
+       json_close_object
+}
+
+_proto_push_string() {
+       json_add_string "" "$1"
+}
+
+_proto_push_route() {
+       local str="$1";
+       local target="${str%%/*}"
+       str="${str#*/}"
+       local mask="${str%%/*}"
+       str="${str#*/}"
+       local gw="${str%%/*}"
+       str="${str#*/}"
+       local metric="${str%%/*}"
+       str="${str#*/}"
+       local valid="${str%%/*}"
+       str="${str#*/}"
+       local source="${str}"
+
+       json_add_object ""
+       json_add_string target "$target"
+       json_add_string netmask "$mask"
+       [ -n "$gw" ] && json_add_string gateway "$gw"
+       [ -n "$metric" ] && json_add_int metric "$metric"
+       [ -n "$valid" ] && json_add_int valid "$valid"
+       [ -n "$source" ] && json_add_string source "$source"
+       json_close_object
+}
+
+_proto_push_array() {
+       local name="$1"
+       local val="$2"
+       local cb="$3"
+
+       [ -n "$val" ] || return 0
+       json_add_array "$name"
+       for item in $val; do
+               eval "$cb \"\$item\""
+       done
+       json_close_array
+}
+
+_proto_notify() {
+       local interface="$1"
+       local options="$2"
+       json_add_string "interface" "$interface"
+       ubus $options call network.interface notify_proto "$(json_dump)"
+}
+
+proto_send_update() {
+       local interface="$1"
+
+       proto_close_nested
+       json_add_boolean keep "$PROTO_KEEP"
+       _proto_push_array "ipaddr" "$PROTO_IPADDR" _proto_push_ipv4_addr
+       _proto_push_array "ip6addr" "$PROTO_IP6ADDR" _proto_push_ipv6_addr
+       _proto_push_array "routes" "$PROTO_ROUTE" _proto_push_route
+       _proto_push_array "routes6" "$PROTO_ROUTE6" _proto_push_route
+       _proto_push_array "ip6prefix" "$PROTO_PREFIX6" _proto_push_string
+       _proto_push_array "dns" "$PROTO_DNS" _proto_push_string
+       _proto_push_array "dns_search" "$PROTO_DNS_SEARCH" _proto_push_string
+       _proto_notify "$interface"
+}
+
+proto_export() {
+       local var="VAR${_EXPORT_VAR}"
+       _EXPORT_VAR="$(($_EXPORT_VAR + 1))"
+       export -- "$var=$1"
+       append _EXPORT_VARS "$var"
+}
+
+proto_run_command() {
+       local interface="$1"; shift
+
+       json_init
+       json_add_int action 1
+       json_add_array command
+       while [ $# -gt 0 ]; do
+               json_add_string "" "$1"
+               shift
+       done
+       json_close_array
+       [ -n "$_EXPORT_VARS" ] && {
+               json_add_array env
+               for var in $_EXPORT_VARS; do
+                       eval "json_add_string \"\" \"\${$var}\""
+               done
+               json_close_array
+       }
+       _proto_notify "$interface"
+}
+
+proto_kill_command() {
+       local interface="$1"; shift
+
+       json_init
+       json_add_int action 2
+       [ -n "$1" ] && json_add_int signal "$1"
+       _proto_notify "$interface"
+}
+
+proto_notify_error() {
+       local interface="$1"; shift
+
+       json_init
+       json_add_int action 3
+       json_add_array error
+       while [ $# -gt 0 ]; do
+               json_add_string "" "$1"
+               shift
+       done
+       json_close_array
+       _proto_notify "$interface"
+}
+
+proto_block_restart() {
+       local interface="$1"; shift
+
+       json_init
+       json_add_int action 4
+       _proto_notify "$interface"
+}
+
+proto_set_available() {
+       local interface="$1"
+       local state="$2"
+       json_init
+       json_add_int action 5
+       json_add_boolean available "$state"
+       _proto_notify "$interface"
+}
+
+proto_add_host_dependency() {
+       local interface="$1"
+       local host="$2"
+       local ifname="$3"
+
+       # execute in subshell to not taint callers env
+       # see tickets #11046, #11545, #11570
+       (
+               json_init
+               json_add_int action 6
+               json_add_string host "$host"
+               [ -n "$ifname" ] && json_add_string ifname "$ifname"
+               _proto_notify "$interface" -S
+       )
+}
+
+proto_setup_failed() {
+       local interface="$1"
+       json_init
+       json_add_int action 7
+       _proto_notify "$interface"
+}
+
+init_proto() {
+       proto="$1"; shift
+       cmd="$1"; shift
+
+       case "$cmd" in
+               dump)
+                       add_protocol() {
+                               no_device=0
+                               available=0
+
+                               add_default_handler "proto_$1_init_config"
+
+                               json_init
+                               json_add_string "name" "$1"
+                               json_add_array "config"
+                               eval "proto_$1_init_config"
+                               json_close_array
+                               json_add_boolean no-device "$no_device"
+                               json_add_boolean available "$available"
+                               json_dump
+                       }
+               ;;
+               setup|teardown)
+                       interface="$1"; shift
+                       data="$1"; shift
+                       ifname="$1"; shift
+
+                       add_protocol() {
+                               [[ "$proto" == "$1" ]] || return 0
+
+                               case "$cmd" in
+                                       setup) _proto_do_setup "$1";;
+                                       teardown) _proto_do_teardown "$1" ;;
+                                       *) return 1 ;;
+                               esac
+                       }
+               ;;
+       esac
+}