You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

402 lines
7.8 KiB
Bash

NETIFD_MAIN_DIR="${NETIFD_MAIN_DIR:-/lib/netifd}"
. /usr/share/libubox/jshn.sh
. $NETIFD_MAIN_DIR/utils.sh
proto_config_add_int() {
config_add_int "$@"
}
proto_config_add_string() {
config_add_string "$@"
}
proto_config_add_boolean() {
config_add_boolean "$@"
}
_proto_do_teardown() {
json_load "$data"
eval "proto_$1_teardown \"$interface\" \"$ifname\""
}
_proto_do_renew() {
json_load "$data"
eval "proto_$1_renew \"$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"
local class="$6"
append PROTO_IP6ADDR "$address/$mask/$preferred/$valid/$offlink/$class"
}
proto_add_ipv4_route() {
local target="$1"
local mask="$2"
local gw="$3"
local source="$4"
local metric="$5"
append PROTO_ROUTE "$target/$mask/$gw/$metric///$source"
}
proto_add_ipv6_route() {
local target="$1"
local mask="$2"
local gw="$3"
local metric="$4"
local valid="$5"
local source="$6"
local table="$7"
append PROTO_ROUTE6 "$target/$mask/$gw/$metric/$valid/$table/$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%%/*}"
str="${str#*/}"
class="${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"
[ -n "$class" ] && json_add_string class "$class"
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 table="${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"
[ -n "$table" ] && json_add_string table "$table"
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
no_proto_task=0
available=0
renew_handler=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 no-proto-task "$no_proto_task"
json_add_boolean available "$available"
json_add_boolean renew-handler "$renew_handler"
json_add_boolean lasterror "$lasterror"
json_dump
}
;;
setup|teardown|renew)
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" ;;
renew) _proto_do_renew "$1" ;;
*) return 1 ;;
esac
}
;;
esac
}