ppp: add config options to tune discovery timeout and attempts
[openwrt/openwrt.git] / package / network / services / ppp / files / ppp.sh
index f07b11f3fd34fa114552700308de50869c3d9aaf..b553effd889e7662f366793665c789ed0d0c0ff2 100755 (executable)
 
 [ -n "$INCLUDE_ONLY" ] || {
        . /lib/functions.sh
+       . /lib/functions/network.sh
        . ../netifd-proto.sh
        init_proto "$@"
 }
 
+ppp_select_ipaddr()
+{
+       local subnets=$1
+       local res
+       local res_mask
+
+       for subnet in $subnets; do
+               local addr="${subnet%%/*}"
+               local mask="${subnet#*/}"
+
+               if [ -n "$res_mask" -a "$mask" != 32 ]; then
+                       [ "$mask" -gt "$res_mask" ] || [ "$res_mask" = 32 ] && {
+                               res="$addr"
+                               res_mask="$mask"
+                       }
+               elif [ -z "$res_mask" ]; then
+                       res="$addr"
+                       res_mask="$mask"
+               fi
+       done
+
+       echo "$res"
+}
+
+ppp_exitcode_tostring()
+{
+       local errorcode=$1
+       [ -n "$errorcode" ] || errorcode=5
+
+       case "$errorcode" in
+               0) echo "OK" ;;
+               1) echo "FATAL_ERROR" ;;
+               2) echo "OPTION_ERROR" ;;
+               3) echo "NOT_ROOT" ;;
+               4) echo "NO_KERNEL_SUPPORT" ;;
+               5) echo "USER_REQUEST" ;;
+               6) echo "LOCK_FAILED" ;;
+               7) echo "OPEN_FAILED" ;;
+               8) echo "CONNECT_FAILED" ;;
+               9) echo "PTYCMD_FAILED" ;;
+               10) echo "NEGOTIATION_FAILED" ;;
+               11) echo "PEER_AUTH_FAILED" ;;
+               12) echo "IDLE_TIMEOUT" ;;
+               13) echo "CONNECT_TIME" ;;
+               14) echo "CALLBACK" ;;
+               15) echo "PEER_DEAD" ;;
+               16) echo "HANGUP" ;;
+               17) echo "LOOPBACK" ;;
+               18) echo "INIT_FAILED" ;;
+               19) echo "AUTH_TOPEER_FAILED" ;;
+               20) echo "TRAFFIC_LIMIT" ;;
+               21) echo "CNID_AUTH_FAILED";;
+               *) echo "UNKNOWN_ERROR" ;;
+       esac
+}
+
 ppp_generic_init_config() {
        proto_config_add_string username
        proto_config_add_string password
        proto_config_add_string keepalive
+       proto_config_add_boolean keepalive_adaptive
        proto_config_add_int demand
        proto_config_add_string pppd_options
        proto_config_add_string 'connect:file'
        proto_config_add_string 'disconnect:file'
-       proto_config_add_boolean ipv6
+       [ -e /proc/sys/net/ipv6 ] && proto_config_add_string ipv6
        proto_config_add_boolean authfail
        proto_config_add_int mtu
        proto_config_add_string pppname
+       proto_config_add_string unnumbered
+       proto_config_add_boolean persist
+       proto_config_add_int maxfail
+       proto_config_add_int holdoff
 }
 
 ppp_generic_setup() {
        local config="$1"; shift
+       local localip
+
+       json_get_vars ip6table demand keepalive keepalive_adaptive username password pppd_options pppname unnumbered persist maxfail holdoff peerdns
+
+       [ ! -e /proc/sys/net/ipv6 ] && ipv6=0 || json_get_var ipv6 ipv6
 
-       json_get_vars ipv6 demand keepalive username password pppd_options pppname
        if [ "$ipv6" = 0 ]; then
                ipv6=""
-       else
+       elif [ -z "$ipv6" -o "$ipv6" = auto ]; then
                ipv6=1
+               autoipv6=1
        fi
+
        if [ "${demand:-0}" -gt 0 ]; then
                demand="precompiled-active-filter /etc/ppp/filter demand idle $demand"
        else
-               demand="persist"
+               demand=""
+       fi
+       if [ -n "$persist" ]; then
+               [ "${persist}" -lt 1 ] && persist="nopersist" || persist="persist"
+       fi
+       if [ -z "$maxfail" ]; then
+               [ "$persist" = "persist" ] && maxfail=0 || maxfail=1
        fi
-       [ "${keepalive:-0}" -lt 1 ] && keepalive=""
        [ -n "$mtu" ] || json_get_var mtu mtu
        [ -n "$pppname" ] || pppname="${proto:-ppp}-$config"
+       [ -n "$unnumbered" ] && {
+               local subnets
+               ( proto_add_host_dependency "$config" "" "$unnumbered" )
+               network_get_subnets subnets "$unnumbered"
+               localip=$(ppp_select_ipaddr "$subnets")
+               [ -n "$localip" ] || {
+                       proto_block_restart "$config"
+                       return
+               }
+       }
+
+       [ -n "$keepalive" ] || keepalive="5 1"
 
-       local interval="${keepalive##*[, ]}"
-       [ "$interval" != "$keepalive" ] || interval=5
+       local lcp_failure="${keepalive%%[, ]*}"
+       local lcp_interval="${keepalive##*[, ]}"
+       local lcp_adaptive="lcp-echo-adaptive"
+       [ "${lcp_failure:-0}" -lt 1 ] && lcp_failure=""
+       [ "$lcp_interval" != "$keepalive" ] || lcp_interval=5
+       [ "${keepalive_adaptive:-1}" -lt 1 ] && lcp_adaptive=""
        [ -n "$connect" ] || json_get_var connect connect
        [ -n "$disconnect" ] || json_get_var disconnect disconnect
 
        proto_run_command "$config" /usr/sbin/pppd \
                nodetach ipparam "$config" \
                ifname "$pppname" \
-               ${keepalive:+lcp-echo-interval $interval lcp-echo-failure ${keepalive%%[, ]*}} \
+               ${localip:+$localip:} \
+               ${lcp_failure:+lcp-echo-interval $lcp_interval lcp-echo-failure $lcp_failure $lcp_adaptive} \
                ${ipv6:++ipv6} \
+               ${autoipv6:+set AUTOIPV6=1} \
+               ${ip6table:+set IP6TABLE=$ip6table} \
+               ${peerdns:+set PEERDNS=$peerdns} \
                nodefaultroute \
                usepeerdns \
-               $demand maxfail 1 \
+               $demand $persist maxfail $maxfail \
+               ${holdoff:+holdoff "$holdoff"} \
                ${username:+user "$username" password "$password"} \
                ${connect:+connect "$connect"} \
                ${disconnect:+disconnect "$disconnect"} \
                ip-up-script /lib/netifd/ppp-up \
-               ipv6-up-script /lib/netifd/ppp-up \
+               ${ipv6:+ipv6-up-script /lib/netifd/ppp6-up} \
                ip-down-script /lib/netifd/ppp-down \
-               ipv6-down-script /lib/netifd/ppp-down \
+               ${ipv6:+ipv6-down-script /lib/netifd/ppp-down} \
                ${mtu:+mtu $mtu mru $mtu} \
                "$@" $pppd_options
 }
 
 ppp_generic_teardown() {
        local interface="$1"
+       local errorstring=$(ppp_exitcode_tostring $ERROR)
 
        case "$ERROR" in
+               0)
+               ;;
+               2)
+                       proto_notify_error "$interface" "$errorstring"
+                       proto_block_restart "$interface"
+               ;;
                11|19)
-                       proto_notify_error "$interface" AUTH_FAILED
                        json_get_var authfail authfail
+                       proto_notify_error "$interface" "$errorstring"
                        if [ "${authfail:-0}" -gt 0 ]; then
                                proto_block_restart "$interface"
                        fi
                ;;
-               2)
-                       proto_notify_error "$interface" INVALID_OPTIONS
-                       proto_block_restart "$interface"
+               *)
+                       proto_notify_error "$interface" "$errorstring"
                ;;
        esac
+
        proto_kill_command "$interface"
 }
 
@@ -90,6 +191,7 @@ proto_ppp_init_config() {
        ppp_generic_init_config
        no_device=1
        available=1
+       lasterror=1
 }
 
 proto_ppp_setup() {
@@ -107,6 +209,11 @@ proto_pppoe_init_config() {
        ppp_generic_init_config
        proto_config_add_string "ac"
        proto_config_add_string "service"
+       proto_config_add_string "host_uniq"
+       proto_config_add_int "padi_attempts"
+       proto_config_add_int "padi_timeout"
+
+       lasterror=1
 }
 
 proto_pppoe_setup() {
@@ -122,11 +229,17 @@ proto_pppoe_setup() {
 
        json_get_var ac ac
        json_get_var service service
+       json_get_var host_uniq host_uniq
+       json_get_var padi_attempts padi_attempts
+       json_get_var padi_timeout padi_timeout
 
        ppp_generic_setup "$config" \
                plugin rp-pppoe.so \
                ${ac:+rp_pppoe_ac "$ac"} \
                ${service:+rp_pppoe_service "$service"} \
+               ${host_uniq:+host-uniq "$host_uniq"} \
+               ${padi_attempts:+pppoe-padi-attempts $padi_attempts} \
+               ${padi_timeout:+pppoe-padi-timeout $padi_timeout} \
                "nic-$iface"
 }
 
@@ -142,6 +255,7 @@ proto_pppoa_init_config() {
        proto_config_add_string "encaps"
        no_device=1
        available=1
+       lasterror=1
 }
 
 proto_pppoa_setup() {
@@ -172,18 +286,21 @@ proto_pppoa_teardown() {
 proto_pptp_init_config() {
        ppp_generic_init_config
        proto_config_add_string "server"
+       proto_config_add_string "interface"
        available=1
        no_device=1
+       lasterror=1
 }
 
 proto_pptp_setup() {
        local config="$1"
        local iface="$2"
 
-       local ip serv_addr server
-       json_get_var server server && {
+       local ip serv_addr server interface
+       json_get_vars interface server
+       [ -n "$server" ] && {
                for ip in $(resolveip -t 5 "$server"); do
-                       ( proto_add_host_dependency "$config" "$ip" )
+                       ( proto_add_host_dependency "$config" "$ip" $interface )
                        serv_addr=1
                done
        }