]> git.ipfire.org Git - network.git/commitdiff
Rework ppp network functionality and introduce the pppd-angel.
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 12 May 2013 20:01:18 +0000 (22:01 +0200)
committerroot <root@ipfire.localdomain>
Sun, 12 May 2013 20:01:18 +0000 (22:01 +0200)
functions.ppp
helpers/pppd-angel [moved from helpers/pppd-config-helper with 69% similarity]

index 05ebed56e0738035990b025b7e0e07fe788c9084..191baba2b89463ccc90b45914b5a864702fae3ad 100644 (file)
 
 PPP_SUPPORTED_AUTH_METHODS="chap pap"
 
-function pppd_start() {
-       local interface=${1}
-       assert isset interface
+EXIT_PPPD_ERROR=${EXIT_ERROR}
+EXIT_PPPD_ERROR_FATAL=$(( ${EXIT_ERROR} + 1 ))
 
-       # This will block until the connection has been established or
-       # pppd exited.
-       service_start "pppd@${interface}.service"
+# 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 ))
+
+               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.
+                               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.
+               sleep ${holdoff_time}
+       done
+}
 
-       # Get the exit code of the ppp daemon and figure out
-       # how to handle this.
-       local ret=$(service_get_exitcode "pppd@${interface}.service")
+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)
-                       return ${EXIT_OK}
+                       # 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)
-                       error "pppd crashed for an unknown reason"
+                       # 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)
-                       error "pppd: Configuration error"
+                       # 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)
-                       error "pppd terminated"
+                       # 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)
-                       error "pppd: Link terminated by modem"
+                       # 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)
-                       error "pppd: Authentication failed"
+                       # We failed to authenticate ourselves to the peer.
+                       log ERROR "pppd: Authentication failed"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
                        ;;
                *)
-                       error "pppd: Unhandled exit code: ${ret}"
+                       log ERROR "pppd: Unhandled exit code: ${ret}"
+                       error_code=${EXIT_PPPD_ERROR_FATAL}
                        ;;
        esac
 
-       return ${ret}
+       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 interface=${1}
-       assert isset interface
+       local device="${1}"
+       assert isset device
 
-       service_stop "pppd@${interface}.service"
+       service_stop "pppd@${device}.service"
 }
 
 function pppd_status() {
-       local interface=${1}
-       assert isset interface
+       local device="${1}"
+       assert isset device
 
-       service_status "pppd@${interface}.service"
+       service_status "pppd@${device}.service"
 }
 
 function ppp_common_ip_pre_up() {
@@ -191,12 +360,6 @@ function ppp_accounting() {
                --rcvd="${BYTES_RCVD}" --sent="${BYTES_SENT}"
 }
 
-function pppd_exec() {
-       log DEBUG "Running pppd with parameters '$@'."
-
-       pppd $@ > /dev/null
-}
-
 function pppd_write_config() {
        local file=${1}; shift
        assert isset file
@@ -419,7 +582,7 @@ function pppd_write_config() {
                print "# Disable the compression"
                print "noccp noaccomp nodeflate nopcomp novj novjccomp nobsdcomp nomppe"
 
-               print "noipdefault updetach debug"
+               print "noipdefault nodetach debug"
        ) >> ${file}
 
        return ${EXIT_OK}
similarity index 69%
rename from helpers/pppd-config-helper
rename to helpers/pppd-angel
index 6f1dae95c051a4b2dd8f5fdbd64b2a9a9f74e5df..c6c94df29b59fa7d5b8c625bb01e8e5c47672d54 100755 (executable)
@@ -2,7 +2,7 @@
 ###############################################################################
 #                                                                             #
 # IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2012  IPFire Network Development Team                         #
+# Copyright (C) 2013  IPFire Network Development Team                         #
 #                                                                             #
 # This program is free software: you can redistribute it and/or modify        #
 # it under the terms of the GNU General Public License as published by        #
 
 . /usr/lib/network/functions
 
-action="${1}"
-assert isset action
+function main() {
+       local zone="${1}"
+       assert isset zone
 
-zone="${2}"
-assert isset zone
-assert zone_exists ${zone}
+       if ! zone_exists "${zone}"; then
+               log ERROR "Must pass valid zone: ${zone}"
+               return ${EXIT_ERROR}
+       fi
 
-config_file="${RUN_DIR}/ppp/${zone}/pppd.conf"
+       # Find the hook of the zone, we got.
+       local hook="$(zone_get_hook "${zone}")"
+       assert isset hook
 
-case "${action}" in
-       create)
-               # Create the configuration file for this zone.
-               hook=$(zone_get_hook ${zone})
-               assert isset hook
+       # Write pppd configuration file.
+       local config_file="${RUN_DIR}/ppp/${zone}/pppd.conf"
+       hook_exec zone "${hook}" "ppp_write_config" "${zone}" "${config_file}"
 
-               hook_exec zone ${hook} ppp_write_config \
-                       ${zone} ${config_file}
-               exit $?
-               ;;
+       # Create trap function
+       function cleanup() {
+               rm -f "${config_file}"
+       }
+       trap "cleanup" EXIT TERM KILL
 
-       remove)
-               rm -f ${config_file}
-               ;;
+       # Start the angel process.
+       pppd_angel "${zone}" "${config_file}"
+}
 
-       *)
-               log ERROR "Unknown action passed: ${action}"
-               exit ${EXIT_ERROR}
-               ;;
-esac
+main "$@" || exit $?
 
 exit ${EXIT_OK}