#!/bin/bash # Copyright (c) 2004-2005 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # function rename wrapper - remove for baselayout-1.12.x if [[ $( type -t bash_variable ) != "function" ]] ; then bash_variable() { interface_variable "$*" } fi # char* pppd_provides(void) # # Returns a string to change module definition for starting up pppd_provides() { echo "ppp" } # void pppd_depend(void) # # Sets up the dependancies for the module pppd_depend() { after interface before dhcp } # bool pppd_check_installed(void) # # Returns 1 if pppd is installed, otherwise 0 pppd_check_installed() { if [[ ! -x /usr/sbin/pppd ]]; then ${1:-false} && eerror "For PPP support, emerge net-dialup/ppp" return 1 fi return 0 } # bool pppd_check_depends(void) # # Checks to see if we have the needed functions pppd_check_depends() { return 0 } # char *pppd_regex_escape(char *string) # # Returns the supplied string with any special regex # characters escaped so they don't provide regex intructions # This may be a candidate for adding to /sbin/functions.sh or # net-scripts functions at some point pppd_regex_escape() { local regex="$*" regex="${regex//\\/\\\\}" regex="${regex//\*/\\*}" regex="${regex//[/\[}" regex="${regex//]/\]}" regex="${regex//./\.}" regex="${regex//\$/\\$}" regex="${regex//^/\^}" regex="${regex//(/\(}" regex="${regex//)/\)}" regex="${regex//\?/\\?}" regex="${regex//+/\+}" regex="${regex//{/\{}" regex="${regex//\}/\}}" echo "${regex}" } # bool pppd_update_secrets_file(char* filepath, char* username, \ # char* remotename, char* password) # # Add/update PAP/CHAP authentication information pppd_update_secrets_file() { local file="$1" username="$2" remote="$3" password="$4" local tmpfile="/tmp/ppp-secret.$$" # Build an egrep to find a line in /etc/ppp/{pap,chap}-secrets local euser=$( pppd_regex_escape "${username}" ) local epassword=$( pppd_regex_escape "${password}" ) local regex='^[[:blank:]]*[\"]?'"${euser}"'[\"]?[[:blank:]]*' regex="${regex}"'[\"]?'"${remote}"'[\"]?[[:blank:]]*' # The find regex needs to search for a matching password too local find_regex="${regex}"'[\"]?'"${epassword}"'([\"[[:blank:]]]?|$)' # Don't update if the information is already there [[ -e ${file} ]] && egrep -q "${find_regex}" "${file}" && return 0 # Create our tmp file with secure permissions touch "${tmpfile}" || return 1 chmod 0600 "${tmpfile}" || return 1 # Now dump the secrets file minus any current security info that # matches what we want to insert into our temporary file and move that back # to the secrets file. We do this because grep cannot read and write to # the same fd at the same time (which makes sense) [[ -e "${file}" ]] && egrep -v "${regex}" "${file}" > "${tmpfile}" # Escape the \ symbol in the username and password so that echo -e # does not expand it username="${username//\\/\\\\}" password="${password//\\/\\\\}" echo -e "\"${username}\"\t\"${remote}\"\t\"${password}\"" >> "${tmpfile}" vewarn "Authentication info has been added to ${file}" mv "${tmpfile}" "${file}" || return 1 return 0 } # bool pppd_start(char *iface) # # Start PPP on an interface by calling pppd # # Returns 0 (true) when successful, otherwise 1 pppd_start() { local iface="$1" ifvar=$( bash_variable "$1" ) opts="" link if [[ ${iface%%[0-9]*} != "ppp" ]]; then eerror "PPP can only be invoked from net.ppp[0-9]" return 1 fi local unit="${iface#ppp}" if [[ -z ${unit} ]] ; then eerror "PPP requires a unit - use net.ppp[0-9] instead of net.ppp" return 1 fi # PPP requires a link to communicate over - normally a serial port # PPPoE communicates over ethernet # PPPoA communictes over ATM # In all cases, the link needs to be available before we start PPP eval link=\"\$\{link_${ifvar}\}\" if [[ -z ${link} ]]; then eerror "link_${ifvar} has not been set in /etc/conf.d/net" return 1 fi # Might or might not be set in conf.d/net local user password i eval username=\"\$\{username_${ifvar}\}\" eval password=\"\$\{password_${ifvar}\}\" #Add/update info in PAP/CHAP secrets files if [[ -n ${username} && -n ${password} ]]; then for i in chap pap ; do if ! pppd_update_secrets_file "/etc/ppp/${i}-secrets" \ "${username}" "${iface}" "${password}" ; then eerror "Failed to update /etc/ppp/${i}-secrets" return 1 fi done fi # Load any commandline options eval opts=\"\$\{pppd_${ifvar}\[@\]}\" # We don't work if nodetach or unit is set for i in nodetach unit ; do if [[ " ${opts} " == *" ${i} "* ]]; then eerror "The option \"${i}\" is not allowed" return 1 fi done # Check for mtu/mru local mtu eval mtu=\"\$\{mtu_${ifvar}\}\" if [[ -n ${mtu} ]]; then [[ " ${opts} " != *" mtu "* ]] && opts="${opts} mtu ${mtu}" [[ " ${opts} " != *" mru "* ]] && opts="${opts} mru ${mtu}" fi # Detach if we're not idling [[ " ${opts} " != *" idle "* && " ${opts} " != *" updetach "* ]] \ && opts="${opts} updetach" # Setup auth info [[ -n ${username} ]] && opts="user ${username} ${opts}" opts="remotename ${iface} ${opts}" # Load a custom interface configuration file if it exists [[ -f "/etc/ppp/options.${iface}" ]] \ && opts="${opts} file /etc/ppp/options.${iface}" # Set forced options opts="unit ${unit} persist maxfail 0 ${opts}" local -a plugins eval plugins=( \"\$\{plugins_${ifvar}\}\" ) for (( i=0; i<${#plugins[@]}; i++ )); do local -a plugin=( ${plugins[i]} ) # Bound to be some users who do this [[ ${plugin[0]} == "pppoe" ]] && plugin[0]="rp-pppoe" [[ ${plugin[0]} == "pppoa" ]] && plugin[0]="pppoatm" [[ ${plugin[0]} == "rp-pppoe" ]] && opts="${opts} connect true" opts="${opts} plugin ${plugin[0]}.so ${plugin[@]:1}" [[ ${plugin[0]} == "rp-pppoe" ]] && opts="${opts} ${link}" done if [[ " ${opts} " == *" plugin rp-pppoe.so "* ]]; then # Ensure that the link exists and is up interface_exists "${link}" true || return 1 interface_up "${link}" # Load the pppoe kernel module - if this fails, we have to hope # that pppoe support is compiled into the kernel modprobe pppoe 2>/dev/null fi ebegin "Running pppd" i=$( /usr/sbin/pppd ${opts} ) eend $? "${i}" || return 1 local addr=$( interface_get_address "${iface}" ) einfo "${iface} received address ${addr}" } # bool pppd_stop(char *iface) # # Stop PPP link by killing the associated pppd process # # Returns 0 (true) if no process to kill or it terminates successfully, # otherwise non-zero (false) pppd_stop() { local iface="$1" pidfile="/var/run/$1.pid" [[ ! -s ${pidfile} ]] && return 0 local pid=$(<"${pidfile}") einfo "Stopping pppd on ${iface}" kill -s TERM "${pid}" process_finished "${pid}" /usr/sbin/pppd eend $? }