Index: src/env_whitelist =================================================================== --- src/env_whitelist (revision 1614) +++ src/env_whitelist (working copy) @@ -8,10 +8,13 @@ # NB: Do not modify below this line if you do not know what you are doing!! # -# Hotplug ? -IN_BACKGROUND +# Hotplug IN_HOTPLUG +# RC network script support +IN_BACKGROUND +RC_INTERFACE_KEEP_CONFIG + # Default shell stuff SHELL USER Index: net-scripts/net.modules.d/ifconfig =================================================================== --- lib/rcscripts/net.modules.d/ifconfig (revision 1614) +++ net-scripts/net.modules.d/ifconfig (working copy) @@ -394,6 +394,24 @@ return ${r} } +# void ifconfig_route_metric(char* interface, int metric) +# +# Change all routes for an interface to a given metric +ifconfig_route_metric() { + local dest gateway mask flags metric ref use + route -n | grep " $1$" | { + while read dest gateway mask flags metric ref use ; do + if [[ ${gateway} != "0.0.0.0" ]]; then + gateway="gw ${gateway}" + else + unset gateway + fi + route del ${dest} + route add -net ${dest} netmask ${mask} ${gateway} metric "$2" dev "$1" + done + } +} + # void ifconfig_default_route(char* interface, char* gateway_ip, int metric) # # Force default route to the specified gateway Index: net-scripts/net.modules.d/helpers.d/pppd-wrapper =================================================================== --- lib/rcscripts/net.modules.d/helpers.d/pppd-wrapper (revision 0) +++ net-scripts/net.modules.d/helpers.d/pppd-wrapper (revision 0) @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright (c) 2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# Contributed by Roy Marples (uberlord@gentoo.org) + +action="$1" +interface="$2" +export IN_BACKGROUND="true" +. /lib/rcscripts/net.modules.d/helpers.d/module-loader +resolv="${statedir}/${interface}/resolv.conf" + +if [[ ${action} == "up" ]]; then + if [[ -n ${DNS1} || -n ${DNS2} ]]; then + echo "# Generated by pppd for interface $1" > "${resolv}" + chmod 0644 "${resolv}" + [ -n ${DNS1} ] && echo "nameserver ${DNS1}" >> "${resolv}" + [ -n ${DNS2} ] && echo "nameserver ${DNS2}" >> "${resolv}" + fi + + # Calculate the metric for our routes + ifvar=$( bash_variable "${interface}" ) + eval metric=\"\$\{metric_${ifvar}\}\" + if [[ -z ${metric} ]]; then + if [[ ${RC_AUTO_INTERFACE} == "yes" ]]; then + metric=$( calculate_metric "${interface}" ) + else + metric="0" + fi + eval metric_${ifvar}="${metric}" + fi + + [[ ${metric} != "0" ]] && interface_route_metric "${interface}" "${metric}" + + export RC_INTERFACE_KEEP_CONFIG="yes" + /etc/init.d/net."${interface}" start +else + rm -f "${resolv}" + /etc/init.d/net."${interface}" stop +fi + +# vim:ts=4 Property changes on: net-scripts/net.modules.d/helpers.d/pppd-wrapper ___________________________________________________________________ Name: svn:executable + * Index: net-scripts/net.modules.d/helpers.d/functions =================================================================== --- lib/rcscripts/net.modules.d/helpers.d/functions (revision 1614) +++ net-scripts/net.modules.d/helpers.d/functions (working copy) @@ -96,21 +96,19 @@ # (ie a state dir exists) # require_gateway defaults to false order_interfaces() { - local ifaces - - if [[ ${1:-false} == "true" ]]; then - ifaces=$(awk '$2!="Gateway" { print $7, $1 }' /proc/net/route \ + local ifaces extra + + ${1:-false} && extra=' && $2=="00000000"' + ifaces=$(awk '{if (NR>1 && $1!="lo"'"${extra}"') print $7, $1}' /proc/net/route \ | sort -n | cut -d' ' -f2 | uniq) - else - ifaces=$(awk '$2=="00000000" { print $7, $1 }' /proc/net/route \ - | sort -n | cut -d' ' -f2 ) - fi # Append lo if it's up - if grep -q "^lo[ \t]*" /proc/net/route ; then - ifaces="${ifaces} lo" + if ! ${1:-false} ; then + if grep -q "^lo[ \t]*" /proc/net/route ; then + ifaces="${ifaces} lo" + fi fi - + local i order for i in ${ifaces}; do [[ -d "${statedir}/${i}" ]] && order="${order}${i} " @@ -132,7 +130,7 @@ [[ ! -e "${statedir}/${ifaces[i]}/resolv.conf" ]] && unset ifaces[i] done ifaces=( "${ifaces[@]}" ) - + # No point merging unless there are two or more interfaces [[ ${#ifaces[@]} -lt 2 ]] && return @@ -151,7 +149,7 @@ opts[i]=$( sed -n -e 's/^[ \t]*options[ \t]*\([^#]*\).*/\1#/p;' "${f}" | xargs ) sortlist[i]=$( sed -n -e 's/^[ \t]*sortlist[ \t]*\([^#]*\).*/\1/p' "${f}" ) - if [[ -z ${srvs[i]} && -z ${opts[i]} && -z ${sortlist[i]} ]]; then + if [[ -z ${srvs[i]} && -z ${opts[i]} && -z ${sortlist[i]} && -z ${search[i]} ]]; then unset srvs[i] unset search[i] unset opts[i] Index: net-scripts/net.modules.d/pppd =================================================================== --- lib/rcscripts/net.modules.d/pppd (revision 1614) +++ net-scripts/net.modules.d/pppd (working copy) @@ -6,20 +6,20 @@ # # Sets up the dependancies for the module pppd_depend() { - after interface - before dhcp - provide ppp + after interface + before dhcp + provide ppp } # 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 + if [[ ! -x /usr/sbin/pppd ]]; then + ${1:-false} && eerror "For PPP support, emerge net-dialup/ppp" + return 1 + fi + return 0 } # char *pppd_regex_escape(char *string) @@ -29,25 +29,25 @@ # This may be a candidate for adding to /sbin/functions.sh or # net-scripts functions at some point pppd_regex_escape() { - local escaped_result="$*" - escaped_result=${escaped_result//\\/\\\\} - escaped_result=${escaped_result//./\\.} - escaped_result=${escaped_result//+/\\+} - escaped_result=${escaped_result//(/\\(} - escaped_result=${escaped_result//)/\\)} - escaped_result=${escaped_result//[/\\[} - escaped_result=${escaped_result//]/\\]} - escaped_result=${escaped_result//\{/\\\{} - escaped_result=${escaped_result//\}/\\\}} - escaped_result=${escaped_result//\?/\\\?} - escaped_result=${escaped_result//\*/\\\*} - escaped_result=${escaped_result//\//\\/} - escaped_result=${escaped_result//|/\\|} - escaped_result=${escaped_result//&/\\&} - escaped_result=${escaped_result//~/\\~} - escaped_result=${escaped_result//^/\\^} - escaped_result=${escaped_result//$/\\$} - echo $escaped_result + local escaped_result="$*" + escaped_result=${escaped_result//\\/\\\\} + escaped_result=${escaped_result//./\\.} + escaped_result=${escaped_result//+/\\+} + escaped_result=${escaped_result//(/\\(} + escaped_result=${escaped_result//)/\\)} + escaped_result=${escaped_result//[/\\[} + escaped_result=${escaped_result//]/\\]} + escaped_result=${escaped_result//\{/\\\{} + escaped_result=${escaped_result//\}/\\\}} + escaped_result=${escaped_result//\?/\\\?} + escaped_result=${escaped_result//\*/\\\*} + escaped_result=${escaped_result//\//\\/} + escaped_result=${escaped_result//|/\\|} + escaped_result=${escaped_result//&/\\&} + escaped_result=${escaped_result//~/\\~} + escaped_result=${escaped_result//^/\\^} + escaped_result=${escaped_result//$/\\$} + echo $escaped_result } # bool pppd_update_secrets_file(char* filepath, char* username, \ @@ -55,44 +55,44 @@ # # Add/update PAP/CHAP authentication information pppd_update_secrets_file() { - local filepath="$1" username="$2" remotename="$3" password="$4" - if [[ ! -f ${filepath} ]]; then - touch ${filepath} && \ - chmod 0600 ${filepath} || \ - return 1 - fi - - #escape username and remotename, used in following sed calls - local regex_username=$(pppd_regex_escape ${username}) - local regex_remotename=$(pppd_regex_escape ${remotename}) - local regex_password - local regex_filter="[ \t]*\"?${regex_username}\"?[ \t]*\"?${regex_remotename}\"?[ \t]*" - - #read old password, including " chars - #for being able to distinct when we need to add or update auth info - local old_password=$( - sed -r -e "/^${regex_filter}\".*\"[ \t]*\$/\ - {s/^${regex_filter}(\".*\")[ \t]*\$/\1/;q;};\ - d;" \ - ${filepath} - ) + local filepath="$1" username="$2" remotename="$3" password="$4" + if [[ ! -f ${filepath} ]]; then + touch ${filepath} && \ + chmod 0600 ${filepath} || \ + return 1 + fi - if [[ -z "${old_password}" ]]; then - regex_username=${username//\\/\\\\} - regex_remotename=${remotename//\\/\\\\} - regex_password=${password//\\/\\\\} - regex_password=${password//"/\\"} - sed -r -i -e "\$a\"${regex_username}\" ${regex_remotename} \"${regex_password}\"" ${filepath} - vewarn "Authentication info has been added to ${filepath}" - elif [[ "\"${password//\"/\\\"}\"" != "${old_password}" ]]; then - regex_password=${password//\\/\\\\} - regex_password=${regex_password//\//\\/} - regex_password=${regex_password//&/\\&} - regex_password=${regex_password//\"/\\\\\"} - sed -r -i -e "s/^(${regex_filter}\").*(\"[ \t]*)\$/\1${regex_password}\2/" ${filepath} - vewarn "Authentication info has been updated in ${filepath}" - fi - return 0 + #escape username and remotename, used in following sed calls + local regex_username=$(pppd_regex_escape ${username}) + local regex_remotename=$(pppd_regex_escape ${remotename}) + local regex_password + local regex_filter="[ \t]*\"?${regex_username}\"?[ \t]*\"?${regex_remotename}\"?[ \t]*" + + #read old password, including " chars + #for being able to distinct when we need to add or update auth info + local old_password=$( + sed -r -e "/^${regex_filter}\".*\"[ \t]*\$/\ + {s/^${regex_filter}(\".*\")[ \t]*\$/\1/;q;};\ + d;" \ + ${filepath} + ) + + if [[ -z "${old_password}" ]]; then + regex_username=${username//\\/\\\\} + regex_remotename=${remotename//\\/\\\\} + regex_password=${password//\\/\\\\} + regex_password=${password//"/\\"} + sed -r -i -e "\$a\"${regex_username}\" ${regex_remotename} \"${regex_password}\"" ${filepath} + vewarn "Authentication info has been added to ${filepath}" + elif [[ "\"${password//\"/\\\"}\"" != "${old_password}" ]]; then + regex_password=${password//\\/\\\\} + regex_password=${regex_password//\//\\/} + regex_password=${regex_password//&/\\&} + regex_password=${regex_password//\"/\\\\\"} + sed -r -i -e "s/^(${regex_filter}\").*(\"[ \t]*)\$/\1${regex_password}\2/" ${filepath} + vewarn "Authentication info has been updated in ${filepath}" + fi + return 0 } # bool pppd_start(char *iface) @@ -101,140 +101,165 @@ # # 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 + ${IN_BACKGROUND} && return 0 - 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 + 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 - # 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 + 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 - # Might or might not be set in conf.d/net - local user password i - eval username=\"\$\{username_${ifvar}\}\" - eval password=\"\$\{password_${ifvar}\}\" + # PPP requires a link to communicate over - normally a serial port + # PPPoE communicates over Ethernet + # PPPoA communicates 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 - #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 + # Might or might not be set in conf.d/net + local user password i + eval username=\"\$\{username_${ifvar}\}\" + eval password=\"\$\{password_${ifvar}\}\" - # Load any commandline options - eval opts=\"\$\{pppd_${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 - # We don't work if unit, no detach or linkname is set. - for i in unit nodetach linkname ; do - if [[ " ${opts} " == *" ${i} "* ]]; then - eerror "The option \"${i}\" is not allowed" - return 1 - fi - done + # Load any commandline options + eval opts=\"\$\{pppd_${ifvar}\[@\]}\" - # 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 + # We don't work with these options set by the user + for i in unit nodetach linkname maxfail persist ; do + if [[ " ${opts} " == *" ${i} "* ]]; then + eerror "The option \"${i}\" is not allowed" + return 1 + fi + done - # Set linkname because we need /var/run/ppp-${linkname}.pid - # This pidfile has the advantage of being there, even if ${iface} interface was never started - opts="linkname ${iface} ${opts}" + # 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 - # Setup auth info - [[ -n ${username} ]] && opts="user \"${username}\" ${opts}" - opts="remotename ${iface} ${opts}" + # Set linkname because we need /var/run/ppp-${linkname}.pid + # This pidfile has the advantage of being there, even if ${iface} interface was never started + opts="linkname ${iface} ${opts}" - # Load a custom interface configuration file if it exists - [[ -f "/etc/ppp/options.${iface}" ]] \ - && opts="${opts} file /etc/ppp/options.${iface}" + # Setup auth info + [[ -n ${username} ]] && opts="user '"${username}"' ${opts}" + opts="remotename ${iface} ${opts}" - # Set forced options - opts="unit ${unit} persist maxfail 0 ${opts}" + # Load a custom interface configuration file if it exists + [[ -f "/etc/ppp/options.${iface}" ]] \ + && opts="${opts} file /etc/ppp/options.${iface}" - # Setup connect script - local -a chat - eval chat=( \"\$\{chat_${ifvar}\[@\]\}\" ) - if [[ -n "${chat[@]}" ]]; then - opts="${opts} connect \"/usr/sbin/chat -e -E -v" + # Set forced options + opts="unit ${unit} persist maxfail 0 ${opts}" - local -a phone_number - eval phone_number=( \"\$\{phone_number_${ifvar}\}\" ) - if [[ ${#phone_number[@]} -ge 1 ]]; then - opts="${opts} -T '${phone_number[0]}'" - if [[ ${#phone_number[@]} -ge 2 ]]; then - opts="${opts} -U '${phone_number[1]}'" - fi - fi + # Setup connect script + local -a chat + eval chat=( \"\$\{chat_${ifvar}\[@\]\}\" ) + if [[ -n "${chat[@]}" ]]; then + opts="${opts} connect \"/usr/sbin/chat -e -E -v" - for (( i=0; i<${#chat[@]}; i++ )); do - opts="${opts} '${chat[i]}'" - done + local -a phone_number + eval phone_number=( \"\$\{phone_number_${ifvar}\}\" ) + if [[ ${#phone_number[@]} -ge 1 ]]; then + opts="${opts} -T '${phone_number[0]}'" + if [[ ${#phone_number[@]} -ge 2 ]]; then + opts="${opts} -U '${phone_number[1]}'" + fi + fi - opts="${opts}\"" - fi + for (( i=0; i<${#chat[@]}; i++ )); do + opts="${opts} '${chat[i]}'" + done - # Add plugins - local -a plugins - eval plugins=( \"\$\{plugins_${ifvar}\[@\]\}\" ) - if [[ -n "${plugins[@]}" ]]; then - 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]} == "capi" ]] && plugin[0]="capiplugin" + opts="${opts}\"" + fi - [[ ${plugin[0]} == "rp-pppoe" ]] && opts="${opts} connect true" - opts="${opts} plugin ${plugin[0]}.so ${plugin[@]:1}" - [[ ${plugin[0]} == "rp-pppoe" ]] && opts="${opts} ${link}" - done - fi + # Add plugins + local -a plugins + eval plugins=( \"\$\{plugins_${ifvar}\[@\]\}\" ) + if [[ -n "${plugins[@]}" ]]; then + 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]} == "capi" ]] && plugin[0]="capiplugin" - #Specialized stuff. Insert here actions particular to connection type (pppoe,pppoa,capi) - local insert_link_in_opts=1 - if [[ " ${opts} " == *" plugin rp-pppoe.so "* ]]; then - # Ensure that the link exists and is up - interface_exists "${link}" true || return 1 - interface_up "${link}" + [[ ${plugin[0]} == "rp-pppoe" ]] && opts="${opts} connect true" + opts="${opts} plugin ${plugin[0]}.so ${plugin[@]:1}" + [[ ${plugin[0]} == "rp-pppoe" ]] && opts="${opts} ${link}" + done + fi - # 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 + #Specialized stuff. Insert here actions particular to connection type (pppoe,pppoa,capi) + local insert_link_in_opts=1 + if [[ " ${opts} " == *" plugin rp-pppoe.so "* ]]; then + if [[ ! -e /proc/net/pppoe ]]; then + # Load the PPPoE kernel module + if ! modprobe pppoe ; then + eerror "kernel does not support PPPoE" + return 1 + fi + fi - insert_link_in_opts=0 - fi - [[ ${insert_link_in_opts} -eq 0 ]] || opts="${link} ${opts}" - - ebegin "Running pppd" - i=$( eval /usr/sbin/pppd ${opts} 2>&1 ) - eend $? "${i}" || return 1 + # Ensure that the link exists and is up + interface_exists "${link}" true || return 1 + interface_up "${link}" - if [[ " ${opts} " == *" updetach "* ]]; then - local addr=$( interface_get_address "${iface}" ) - einfo "${iface} received address ${addr}" - fi + insert_link_in_opts=0 + fi + + if [[ " ${opts} " == *" plugin pppoatm.so "* ]]; then + if [[ ! -d /proc/net/atm ]]; then + # Load the PPPoA kernel module + if ! modprobe pppoatm ; then + eerror "kernel does not support PPPoATM" + return 1 + fi + fi + fi + [[ ${insert_link_in_opts} -eq 0 ]] || opts="${link} ${opts}" + + ebegin "Running pppd" + mark_service_inactive "net.${iface}" + local quiet="--quiet" + [[ ${RC_VERBOSE} == "yes" ]] && quiet="" + start-stop-daemon --start ${quiet} --exec /usr/sbin/pppd \ + --pidfile "/var/run/ppp-${iface}.pid" -- ${opts} + eend $? || mark_service_starting "net.${iface}" && return 1 + + if [[ " ${opts} " == *" updetach "* ]]; then + local addr=$( interface_get_address "${iface}" ) + einfo "${iface} received address ${addr}" + fi + + # pppd will call ip-up which will re-call us, so we always + # background at this point + einfo "Backgrounding ..." + exit 0 } # bool pppd_stop(char *iface) @@ -244,15 +269,14 @@ # Returns 0 (true) if no process to kill or it terminates successfully, # otherwise non-zero (false) pppd_stop() { - local iface="$1" pidfile="/var/run/ppp-$1.pid" + ${IN_BACKGROUND} && return 0 + local iface="$1" pidfile="/var/run/ppp-$1.pid" - [[ ! -s ${pidfile} ]] && return 0 + [[ ! -s ${pidfile} ]] && return 0 - local pid - read pid <"${pidfile}" #PID is the first line of the pidfile - einfo "Stopping pppd on ${iface}" - kill -s TERM "${pid}" - process_finished "${pid}" /usr/sbin/pppd - - eend $? + einfo "Stopping pppd on ${iface}" + start-stop-daemon --stop --exec /usr/sbin/pppd --pidfile "${pidfile}" + eend $? } + +# vim: ts=4 Index: net-scripts/net.modules.d/iproute2 =================================================================== --- lib/rcscripts/net.modules.d/iproute2 (revision 1614) +++ net-scripts/net.modules.d/iproute2 (working copy) @@ -309,9 +309,9 @@ # Support net-tools routing too x="${x//gw/via}" - x="${x//-A inet6}" - x="${x//-net}" - [[ " ${x} " == *" -host "* ]] && x="${x//-host} scope host" + x="${x//-A inet6/}" + x="${x//-net/}" + [[ " ${x} " == *" -host "* ]] && x="${x//-host/} scope host" # Attempt to support net-tools route netmask option netmask="${x##* netmask }" @@ -334,6 +334,19 @@ return 0 } +# void iproute2_route_metric(char* interface, int metric) +# +# Change all routes for an interface to a given metric +iproute2_route_metric() { + local route + ip route | grep " dev $1" | { + while read route ; do + ip route del ${route} + ip route add ${route} metric "$2" + done + } +} + # void iproute2_default_route(char* interface, char* gateway_ip, int metric) # # Force default route to the specified gateway, optionally on