]> git.ipfire.org Git - people/ms/network.git/blobdiff - functions.ppp
hostapd: Enable WMM by default.
[people/ms/network.git] / functions.ppp
index 78b967e44d65679fed6cc13f7f9923e0689eecc3..7673648a61be8c2cfe9dc14a9d1d649b66ef72ed 100644 (file)
 #                                                                             #
 ###############################################################################
 
+PPP_SUPPORTED_AUTH_METHODS="chap pap"
+
+EXIT_PPPD_ERROR=${EXIT_ERROR}
+EXIT_PPPD_ERROR_FATAL=$(( ${EXIT_ERROR} + 1 ))
+
+# This function monitors the pppd activity.
+
+function pppd_angel() {
+       local device="${1}"
+       assert isset device
+
+       local config_file="${2}"
+       assert isset config_file
+       shift 2
+
+       local holdoff_time
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --holdoff-time=*)
+                               holdoff_time="$(cli_get_val "${1}")"
+                               ;;
+                       *)
+                               warning "Unrecognized argument: ${1}"
+                               return ${EXIT_ERROR}
+                               ;;
+               esac
+               shift
+       done
+
+       local pppd_ret ret
+       while :; do
+               # Execute ppp daemon.
+               pppd_exec "${device}" "${config_file}"
+               ret=$?
+
+               pppd_ret=$(( ${ret} % 0x0f ))
+               ret=$(( ${ret} >> 6 ))
+
+               log DEBUG "pppd exited with error code ${pppd_ret}"
+
+               case "${ret}" in
+                       ${EXIT_OK})
+                               # pppd terminated gracefully. Propagating...
+                               return ${EXIT_OK}
+                               ;;
+                       ${EXIT_PPPD_ERROR})
+                               # pppd has a (non-fatal) error, in which case we
+                               # restart it instantly, so it will try to re-establish
+                               # the connection.
+                               ;;
+                       ${EXIT_PPPD_ERROR_FATAL})
+                               # pppd has a fatal error. We cannot go on from here
+                               # because there is either no chance to establish a connection
+                               # without any user interaction, or we will damage the system.
+                               log ERROR "Fatal error. Not going to restart pppd."
+                               return ${pppd_ret}
+                               ;;
+                       *)
+                               log ERROR "Invalid return code: ${ret}"
+                               return ${EXIT_ERROR}
+                               ;;
+               esac
+
+               isset holdoff_time || continue
+
+               # When we got here, we need to wait a little bit and restart the
+               # ppp daemon soon.
+               log INFO "Restarting pppd in ${holdoff_time}s"
+               sleep ${holdoff_time}
+       done
+}
+
+function pppd_exec() {
+       local device="${1}"
+       assert isset device
+
+       local config_file="${2}"
+       assert isset config_file
+       shift 2
+
+       # Execute pppd.
+       cmd "pppd file ${config_file} $@"
+       local ret=$?
+
+       # Evaluate return code.
+       local error_code
+       case "${ret}" in
+               0)
+                       # Pppd has detached, or otherwise the connection was successfully
+                       # established and terminated at the peer's request.
+                       log DEBUG "pppd exited gracefully"
+                       error_code=${EXIT_OK}
+                       ;;
+               1)
+                       # An immediately fatal error of some kind occurred, such as an
+                       # essential system call failing, or running out of virtual memory.
+                       log ERROR "pppd crashed for an unknown reason"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               2)
+                       # An error was detected in processing the options given, such as two
+                       # mutually exclusive options being used.
+                       log ERROR "pppd: Configuration error"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               3)
+                       # Pppd is not setuid-root and the invoking user is not root.
+                       log ERROR "pppd: Launched with insufficient privileges"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               4)
+                       # The kernel does not support PPP, for example, the PPP kernel driver is
+                       # not included or cannot be loaded.
+                       log ERROR "pppd: Kernel does not support PPP"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               5)
+                       # Pppd terminated because it was sent a SIGINT, SIGTERM or SIGHUP signal.
+                       log ERROR "pppd: Received SIGINT, SIGTERM or SIGHUP signal"
+                       error_code=${EXIT_PPPD_ERROR}
+                       ;;
+               6)
+                       # The serial port could not be locked.
+                       log ERROR "pppd: Serial port could not be locked"
+                       error_code=${EXIT_PPPD_ERROR}
+                       ;;
+               7)
+                       # The serial port could not be opened.
+                       log ERROR "pppd: Serial port could not be opened"
+                       error_code=${EXIT_PPPD_ERROR}
+                       ;;
+               8)
+                       # The connect script failed (returned a non-zero exit status).
+                       log ERROR "pppd: Connect script failed"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               9)
+                       # The command specified as the argument to the pty option could not be run.
+                       log ERROR "pppd: Could not run pty command"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               10)
+                       # The PPP negotiation failed, that is, it didn't reach the point where at
+                       # least one network protocol (e.g. IP) was running.
+                       log ERROR "pppd: Protocol negotiation failed"
+                       error_code=${EXIT_PPPD_ERROR}
+                       ;;
+               11)
+                       # The peer system failed (or refused) to authenticate itself.
+                       log ERROR "pppd: peer system failed (or refused) to authenticate itself"
+                       error_code=${EXIT_PPPD_ERROR}
+                       ;;
+               12)
+                       # The link was established successfully and terminated because it was idle.
+                       log ERROR "pppd: Terminated because of idleness"
+                       error_code=${EXIT_PPPD_ERROR}
+                       ;;
+               13)
+                       # The link was established successfully and terminated because the connect time
+                       # limit was reached.
+                       log ERROR "pppd: connect time limit was reached"
+                       error_code=${EXIT_PPPD_ERROR}
+                       ;;
+               14)
+                       # Callback was negotiated and an incoming call should arrive shortly.
+                       # We should not be using this, so make it fatal that nobody is able to
+                       # abuse the feature.
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               15)
+                       # The link was terminated because the peer is not responding to echo requests.
+                       log ERROR "pppd: Peer is not responding to echo requests"
+                       error_code=${EXIT_PPPD_ERROR}
+                       ;;
+               16)
+                       # The link was terminated by the modem hanging up.
+                       log ERROR "pppd: Modem hung up"
+                       error_code=${EXIT_PPPD_ERROR}
+                       ;;
+               17)
+                       # The PPP negotiation failed because serial loopback was detected.
+                       log ERROR "pppd: Serial loopback detected"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               18)
+                       # The init script failed (returned a non-zero exit status).
+                       log ERROR "pppd: Init script failed"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               19)
+                       # We failed to authenticate ourselves to the peer.
+                       log ERROR "pppd: Authentication failed"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+               *)
+                       log ERROR "pppd: Unhandled exit code: ${ret}"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
+                       ;;
+       esac
+
+       return $(( (${error_code} << 6) + ${ret} ))
+}
+
+function pppd_start() {
+       local device="${1}"
+       assert isset device
+
+       # This will block until the connection has been established or
+       # pppd exited.
+       service_start "pppd@${device}.service"
+}
+
+function pppd_stop() {
+       local device="${1}"
+       assert isset device
+
+       service_stop "pppd@${device}.service"
+}
+
+function pppd_status() {
+       local device="${1}"
+       assert isset device
+
+       service_status "pppd@${device}.service"
+}
+
 function ppp_common_ip_pre_up() {
        local zone=${1}
        shift
@@ -30,13 +257,10 @@ function ppp_common_ip_pre_up() {
 
        routing_db_from_ppp ${zone} ipv4
 
-       # Request firewall reload
-       event_firewall_reload
-
        return ${EXIT_OK}
 }
 
-function ppp_common_ip_up() {
+function ppp_common_ipv4_up() {
        local zone=${1}
        shift
 
@@ -47,14 +271,12 @@ function ppp_common_ip_up() {
 
        routing_db_set ${zone} ipv4 active 1
        routing_update ${zone} ipv4
-
-       # Emit interface-up event
-       event_interface_up ${zone}
+       routing_default_update
 
        return ${EXIT_OK}
 }
 
-function ppp_common_ip_down() {
+function ppp_common_ipv4_down() {
        local zone=${1}
        shift
 
@@ -67,13 +289,11 @@ function ppp_common_ip_down() {
        # and update the routing table.
        routing_db_remove ${zone} ipv4
        routing_update ${zone} ipv4
+       routing_default_update
 
        # Save accounting information
        ppp_accounting ${zone}
 
-       # Emit interface-up event
-       event_interface_down ${zone}
-
        return ${EXIT_OK}
 }
 
@@ -91,9 +311,7 @@ function ppp_common_ipv6_up() {
 
        routing_db_set ${zone} ipv6 active 1
        routing_update ${zone} ipv6
-
-       # Emit interface-up event
-       event_interface_up ${zone}
+       routing_default_update
 
        return ${EXIT_OK}
 }
@@ -111,13 +329,11 @@ function ppp_common_ipv6_down() {
        # and update the routing table.
        routing_db_remove ${zone} ipv6
        routing_update ${zone} ipv6
+       routing_default_update
 
        # Save accounting information
        ppp_accounting ${zone}
 
-       # Emit interface-up event
-       event_interface_down ${zone}
-
        return ${EXIT_OK}
 }
 
@@ -148,8 +364,254 @@ function ppp_accounting() {
                --rcvd="${BYTES_RCVD}" --sent="${BYTES_SENT}"
 }
 
-function pppd_exec() {
-       log DEBUG "Running pppd with parameters '$@'."
+function pppd_write_config() {
+       local file=${1}; shift
+       assert isset file
+
+       local auth
+       local baudrate
+       local connect_cmd
+       local default_asyncmap="true"
+       local interface
+       local ipv6="true"
+       local lcp_echo_failure=3
+       local lcp_echo_interval=20
+       local linkname
+       local mtu mru
+       local password
+       local plugin plugin_options
+       local pty
+       local refuses
+       local serial="false"
+       local username
+       local value
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --auth=*)
+                               auth=$(cli_get_val ${1})
+                               ;;
+                       --baudrate=*)
+                               baudrate=$(cli_get_val ${1})
+                               assert isoneof baudrate ${SERIAL_BAUDRATES}
+                               ;;
+                       --connect-command=*)
+                               connect_cmd=$(cli_get_val ${1})
+                               ;;
+                       # Enable or disable the use of the default asyncmap.
+                       --default-asyncmap=*)
+                               value=$(cli_get_val ${1})
+                               if enabled value; then
+                                       default_asyncmap="true"
+                               else
+                                       default_asyncmap="false"
+                               fi
+                               ;;
+                       # The name of the created ppp interface.
+                       --interface=*)
+                               interface=$(cli_get_val ${1})
+                               ;;
+                       # IPv6
+                       --ipv6=*)
+                               ipv6="$(cli_get_val ${1})"
+                               ;;
+                       # LCP echo failure.
+                       --lcr-echo-failure=*)
+                               lcr_echo_failure=$(cli_get_val ${1})
+
+                               if ! isinteger ${lcr_echo_failure}; then
+                                       error "--lcr-echo-failure= requires a number"
+                                       return ${EXIT_ERROR}
+                               fi
+                               ;;
+                       # LCP echo interval.
+                       --lcr-echo-interval=*)
+                               lcr_echo_interval=$(cli_get_val ${1})
+
+                               if ! isinteger ${lcr_echo_failure}; then
+                                       error "--lcr-echo-interval= requires a number"
+                                       return ${EXIT_ERROR}
+                               fi
+                               ;;
+                       # Maximum Transmission Unit
+                       --mtu=*)
+                               mtu=$(cli_get_val ${1})
+                               ;;
+                       # Maximum Receive Unit
+                       --mru=*)
+                               mru=$(cli_get_val ${1})
+                               ;;
+                       --password=*)
+                               password=$(cli_get_val ${1})
+                               ;;
+                       --plugin=*)
+                               plugin=$(cli_get_val ${1})
+                               ;;
+                       --plugin-options=*)
+                               plugin_options=$(cli_get_val ${1})
+                               ;;
+                       --pty=*)
+                               pty=$(cli_get_val ${1})
+                               ;;
+                       # Refused authentication methods
+                       --refuse=*)
+                               list_append refuses "$(cli_get_val "${1}")"
+                               error_log "REFUSES $refuses $1"
+                               ;;
+                       # Sets if the modem is a serial device.
+                       --serial=*)
+                               serial=$(cli_get_val ${1})
+                               ;;
+                       --serial-device=*)
+                               serial_device=$(cli_get_val ${1})
+                               ;;
+                       --username=*)
+                               username=$(cli_get_val ${1})
+                               ;;
+                       *)
+                               log WARNING "Unhandled argument: ${1}"
+                               ;;
+               esac
+               shift
+       done
+
+       if [ -z "${interface}" ]; then
+               log ERROR "You need to set the interface name: ${interface}"
+               return ${EXIT_ERROR}
+       fi
+       linkname="${interface}"
 
-       pppd $@ > /dev/null
+       if isset auth; then
+               if ! isoneof ${auth} ${PPP_SUPPORTED_AUTH_METHODS}; then
+                       log ERROR "Unsupported auth method: ${auth}"
+                       return ${EXIT_ERROR}
+               fi
+       fi
+
+       if enabled serial; then
+               assert isset serial_device
+               assert [ -c "${serial_device}" ]
+       fi
+
+       # Set the user credentials.
+       ppp_secret "${username}" "${password}"
+
+       # Write the configuration header.
+       mkdir -p $(dirname ${file}) 2>/dev/null
+       config_header "PPP daemon configuration file" > ${file}
+
+       # At first, set the name of the link.
+       print "linkname ${linkname}\n" >> ${file}
+
+       # Configure the interface/zone name.
+       (
+               print "# Interface name"
+               print "ifname ${interface}"
+               print
+       ) >> ${file}
+
+       # Plugin settings
+       if isset plugin; then
+               (
+                       print "# Plugin settings"
+                       print "plugin ${plugin} ${plugin_options}"
+                       print
+               ) >> ${file}
+       fi
+
+       # pty settings
+       if isset pty; then
+               (
+                       print "# pty settings"
+                       print "pty \"${pty}\""
+                       print
+                ) >> ${file}
+       fi
+
+       # User authentication
+       if isset username; then
+               (
+                       print "# User authentication"
+                       print "user ${username}"
+
+                       print "noauth"
+                       if isset auth; then
+                               print "require-${auth}"
+                       fi
+
+                       # Refused authentication methods
+                       for refuse in ${refuses}; do
+                               print "refuse-${refuse}"
+                       done
+                       print
+               ) >> ${file}
+       fi
+
+       # IPv6
+       if enabled ipv6; then
+               (
+                       print "# IPv6 support"
+                       print "+ipv6"
+                       print
+               ) >> ${file}
+       fi
+
+       # MTU/MRU settings
+       if isset mtu; then
+               isset mru || mru=${mtu}
+
+               (
+                       print "# MTU/MRU settings"
+                       print "mtu ${mtu}"
+                       print "mru ${mru}"
+                       print
+               ) >> ${file}
+       fi
+
+       if enabled serial; then
+               (
+                       print "# Serial modem settings"
+                       print "${serial_device} ${baudrate}"
+                       print "crtscts"
+                       print "lock"
+                       print "modem"
+                       print
+               ) >> ${file}
+
+               # Connect command
+               if isset connect_cmd; then
+                       (
+                               print "# Connect command"
+                               print "connect \"${connect_cmd}\""
+                               print
+                       ) >> ${file}
+               fi
+       fi
+
+       # Default asyncmap.
+       if enabled default_asyncmap; then
+               (
+                       print "# Use the default asyncmap."
+                       print "default-asyncmap"
+                       print
+               ) >> ${file}
+       fi
+
+       # LCP settings.
+       (
+               print "# LCP settings"
+               print "lcp-echo-failure ${lcp_echo_failure}"
+               print "lcp-echo-interval ${lcp_echo_interval}"
+               print
+       ) >> ${file}
+
+       # Add the default settings.
+       (
+               print "# Disable the compression"
+               print "noccp noaccomp nodeflate nopcomp novj novjccomp nobsdcomp nomppe"
+
+               print "noipdefault nodetach debug"
+       ) >> ${file}
+
+       return ${EXIT_OK}
 }