4255ba175b
The program function in depend blocks is now able to search paths by itself. If passed multiple arguments or multiple calls, at least one of the arguments passed must be a program or a shell builtin (eg ip built into busybox). If a qualified path is specified, only that path will be checked, otherwise it will be checked as a builtin, then $PATH will be checked for the named binary (via type). Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
394 lines
8.5 KiB
Bash
394 lines
8.5 KiB
Bash
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
|
|
# Released under the 2-clause BSD license.
|
|
|
|
iproute2_depend()
|
|
{
|
|
program ip
|
|
provide interface
|
|
after ifconfig
|
|
}
|
|
|
|
_up()
|
|
{
|
|
ip link set "${IFACE}" up
|
|
}
|
|
|
|
_down()
|
|
{
|
|
ip link set "${IFACE}" down
|
|
}
|
|
|
|
_exists()
|
|
{
|
|
grep -Eq "^[[:space:]]*${IFACE}:" /proc/net/dev
|
|
}
|
|
|
|
_ifindex()
|
|
{
|
|
local line= i=-2
|
|
while read line; do
|
|
: $(( i += 1 ))
|
|
[ ${i} -lt 1 ] && continue
|
|
case "${line}" in
|
|
"${IFACE}:"*) echo "${i}"; return 0;;
|
|
esac
|
|
done < /proc/net/dev
|
|
|
|
# Return the next available index
|
|
: $(( i += 1 ))
|
|
echo "${i}"
|
|
return 1
|
|
}
|
|
|
|
_is_wireless()
|
|
{
|
|
# Support new sysfs layout
|
|
[ -d /sys/class/net/"${IFACE}"/wireless -o \
|
|
-d /sys/class/net/"${IFACE}"/phy80211 ] && return 0
|
|
|
|
[ ! -e /proc/net/wireless ] && return 1
|
|
grep -Eq "^[[:space:]]*${IFACE}:" /proc/net/wireless
|
|
}
|
|
|
|
_set_flag()
|
|
{
|
|
local flag=$1 opt="on"
|
|
if [ "${flag#-}" != "${flag}" ]; then
|
|
flag=${flag#-}
|
|
opt="off"
|
|
fi
|
|
ip link set "${IFACE}" "${flag}" "${opt}"
|
|
}
|
|
|
|
_get_mac_address()
|
|
{
|
|
local mac=$(LC_ALL=C ip link show "${IFACE}" | sed -n \
|
|
-e 'y/abcdef/ABCDEF/' \
|
|
-e '/link\// s/^.*\<\(..:..:..:..:..:..\)\>.*/\1/p')
|
|
|
|
case "${mac}" in
|
|
00:00:00:00:00:00);;
|
|
44:44:44:44:44:44);;
|
|
FF:FF:FF:FF:FF:FF);;
|
|
"");;
|
|
*) echo "${mac}"; return 0;;
|
|
esac
|
|
|
|
return 1
|
|
}
|
|
|
|
_set_mac_address()
|
|
{
|
|
ip link set "${IFACE}" address "$1"
|
|
}
|
|
|
|
_get_inet_addresses()
|
|
{
|
|
LC_ALL=C ip -family inet addr show "${IFACE}" | \
|
|
sed -n -e 's/.*inet \([^ ]*\).*/\1/p'
|
|
}
|
|
|
|
_get_inet_address()
|
|
{
|
|
set -- $(_get_inet_addresses)
|
|
[ $# = "0" ] && return 1
|
|
echo "$1"
|
|
}
|
|
|
|
_add_address()
|
|
{
|
|
if [ "$1" = "127.0.0.1/8" -a "${IFACE}" = "lo" ]; then
|
|
ip addr add "$@" dev "${IFACE}" 2>/dev/null
|
|
return 0
|
|
fi
|
|
|
|
local address netmask broadcast peer anycast label scope
|
|
local valid_lft preferred_lft home nodad
|
|
local confflaglist
|
|
address="$1" ; shift
|
|
while [ -n "$*" ]; do
|
|
case "$1" in
|
|
netmask)
|
|
netmask="/$(_netmask2cidr "$2")" ; shift ; shift ;;
|
|
broadcast|brd)
|
|
broadcast="$2" ; shift ; shift ;;
|
|
pointopoint|pointtopoint|peer)
|
|
peer="$2" ; shift ; shift ;;
|
|
anycast|label|scope|valid_lft|preferred_lft)
|
|
eval "$1=$2" ; shift ; shift ;;
|
|
home|nodad)
|
|
# FIXME: If we need to reorder these, this will take more code
|
|
confflaglist="${confflaglist} $1" ; shift ;;
|
|
esac
|
|
done
|
|
|
|
# Always scope lo addresses as host unless specified otherwise
|
|
if [ "${IFACE}" = "lo" ]; then
|
|
[ -z "$scope" ] && scope="host"
|
|
fi
|
|
|
|
# figure out the broadcast address if it is not specified
|
|
# This must NOT be set for IPv6 addresses
|
|
if [ "${address#*:}" = "${address}" ]; then
|
|
[ -z "$broadcast" ] && broadcast="+"
|
|
elif [ -n "$broadcast" ]; then
|
|
eerror "Broadcast keywords are not valid with IPv6 addresses"
|
|
return 1
|
|
fi
|
|
|
|
# This must appear on a single line, continuations cannot be used
|
|
set -- "${address}${netmask}" ${peer:+peer} ${peer} ${broadcast:+broadcast} ${broadcast} ${anycast:+anycast} ${anycast} ${label:+label} ${label} ${scope:+scope} ${scope} dev "${IFACE}" ${valid_lft:+valid_lft} $valid_lft ${preferred_lft:+preferred_lft} $preferred_lft $confflaglist
|
|
veinfo ip addr add "$@"
|
|
ip addr add "$@"
|
|
}
|
|
|
|
_add_route()
|
|
{
|
|
local family=
|
|
|
|
if [ "$1" = "-A" -o "$1" = "-f" -o "$1" = "-family" ]; then
|
|
family="-f $2"
|
|
shift; shift
|
|
elif [ "$1" = "-4" ]; then
|
|
family="-f inet"
|
|
shift
|
|
elif [ "$1" = "-6" ]; then
|
|
family="-f inet6"
|
|
shift
|
|
fi
|
|
|
|
if [ $# -eq 3 ]; then
|
|
set -- "$1" "$2" via "$3"
|
|
elif [ "$3" = "gw" ]; then
|
|
local one=$1 two=$2
|
|
shift; shift; shift
|
|
set -- "${one}" "${two}" via "$@"
|
|
fi
|
|
|
|
local cmd= have_metric=false
|
|
while [ -n "$1" ]; do
|
|
case "$1" in
|
|
metric) cmd="${cmd} $1"; have_metric=true;;
|
|
netmask) cmd="${cmd}/$(_netmask2cidr "$2")"; shift;;
|
|
-host|-net);;
|
|
*) cmd="${cmd} $1";;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# We cannot use a metric if we're using a nexthop
|
|
if ! ${have_metric} && \
|
|
[ -n "${metric}" -a \
|
|
"${cmd##* nexthop }" = "$cmd" ]
|
|
then
|
|
cmd="${cmd} metric ${metric}"
|
|
fi
|
|
|
|
veinfo ip ${family} route append ${cmd} dev "${IFACE}"
|
|
ip ${family} route append ${cmd} dev "${IFACE}"
|
|
eend $?
|
|
}
|
|
|
|
_delete_addresses()
|
|
{
|
|
ip addr flush dev "${IFACE}" scope global 2>/dev/null
|
|
ip addr flush dev "${IFACE}" scope site 2>/dev/null
|
|
if [ "${IFACE}" != "lo" ]; then
|
|
ip addr flush dev "${IFACE}" scope host 2>/dev/null
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
_has_carrier()
|
|
{
|
|
return 0
|
|
}
|
|
|
|
_tunnel()
|
|
{
|
|
ip tunnel "$@"
|
|
}
|
|
|
|
# This is just to trim whitespace, do not add any quoting!
|
|
_trim() {
|
|
echo $*
|
|
}
|
|
|
|
# This is our interface to Routing Policy Database RPDB
|
|
# This allows for advanced routing tricks
|
|
_ip_rule_runner() {
|
|
local cmd rules OIFS="${IFS}" family
|
|
if [ "$1" = "-4" -o "$1" = "-6" ]; then
|
|
family="$1"
|
|
shift
|
|
else
|
|
family="-4"
|
|
fi
|
|
cmd="$1"
|
|
rules="$2"
|
|
veindent
|
|
local IFS="$__IFS"
|
|
for ru in $rules ; do
|
|
unset IFS
|
|
ruN="$(_trim "${ru}")"
|
|
[ -z "${ruN}" ] && continue
|
|
vebegin "${cmd} ${ruN}"
|
|
ip $family rule ${cmd} ${ru}
|
|
veend $?
|
|
local IFS="$__IFS"
|
|
done
|
|
IFS="${OIFS}"
|
|
veoutdent
|
|
}
|
|
|
|
iproute2_pre_start()
|
|
{
|
|
local tunnel=
|
|
eval tunnel=\$iptunnel_${IFVAR}
|
|
if [ -n "${tunnel}" ]; then
|
|
# Set our base metric to 1000
|
|
metric=1000
|
|
# Bug#347657: If the mode is 'ipip6' or 'ip6ip6', the -6 must be passed
|
|
# to iproute2 during tunnel creation.
|
|
local ipproto=''
|
|
[ "${tunnel##mode ipip6}" != "${tunnel}" ] && ipproto='-6'
|
|
[ "${tunnel##mode ip6ip6}" != "${tunnel}" ] && ipproto='-6'
|
|
|
|
ebegin "Creating tunnel ${IFVAR}"
|
|
ip ${ipproto} tunnel add ${tunnel} name "${IFACE}"
|
|
eend $? || return 1
|
|
_up
|
|
fi
|
|
|
|
# MTU support
|
|
local mtu=
|
|
eval mtu=\$mtu_${IFVAR}
|
|
[ -n "${mtu}" ] && ip link set "${IFACE}" mtu "${mtu}"
|
|
|
|
# TX Queue Length support
|
|
local len=
|
|
eval len=\$txqueuelen_${IFVAR}
|
|
[ -n "${len}" ] && ip link set "${IFACE}" txqueuelen "${len}"
|
|
|
|
return 0
|
|
}
|
|
|
|
_iproute2_ipv6_tentative()
|
|
{
|
|
# Only check tentative when we have a carrier.
|
|
LC_ALL=C ip link show dev "${IFACE}" | grep -q "NO-CARRIER" && return 1
|
|
LC_ALL=C ip addr show dev "${IFACE}" | \
|
|
grep -q "^[[:space:]]*inet6 .* tentative"
|
|
}
|
|
|
|
iproute2_post_start()
|
|
{
|
|
local n=5
|
|
|
|
# Kernel may not have IP built in
|
|
if [ -e /proc/net/route ]; then
|
|
local rules="$(_get_array "rules_${IFVAR}")"
|
|
if [ -n "${rules}" ]; then
|
|
if ! ip -4 rule list | grep -q "^"; then
|
|
eerror "IP Policy Routing (CONFIG_IP_MULTIPLE_TABLES) needed for ip rule"
|
|
else
|
|
service_set_value "ip_rule" "${rules}"
|
|
einfo "Adding IPv4 RPDB rules"
|
|
_ip_rule_runner -4 add "${rules}"
|
|
fi
|
|
fi
|
|
ip -4 route flush table cache dev "${IFACE}"
|
|
fi
|
|
|
|
# Kernel may not have IPv6 built in
|
|
if [ -e /proc/net/ipv6_route ]; then
|
|
local rules="$(_get_array "rules6_${IFVAR}")"
|
|
if [ -n "${rules}" ]; then
|
|
if ! ip -6 rule list | grep -q "^"; then
|
|
eerror "IPv6 Policy Routing (CONFIG_IPV6_MULTIPLE_TABLES) needed for ip rule"
|
|
else
|
|
service_set_value "ip6_rule" "${rules}"
|
|
einfo "Adding IPv6 RPDB rules"
|
|
_ip_rule_runner -6 add "${rules}"
|
|
fi
|
|
fi
|
|
ip -6 route flush table cache dev "${IFACE}"
|
|
fi
|
|
|
|
if _iproute2_ipv6_tentative; then
|
|
ebegin "Waiting for IPv6 addresses"
|
|
while [ $n -ge 0 ]; do
|
|
_iproute2_ipv6_tentative || break
|
|
sleep 1
|
|
: $(( n -= 1 ))
|
|
done
|
|
[ $n -ge 0 ]
|
|
eend $?
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
iproute2_post_stop()
|
|
{
|
|
# Kernel may not have IP built in
|
|
if [ -e /proc/net/route ]; then
|
|
local rules="$(service_get_value "ip_rule")"
|
|
if [ -n "${rules}" ]; then
|
|
einfo "Removing IPv4 RPDB rules"
|
|
_ip_rule_runner -4 del "${rules}"
|
|
fi
|
|
|
|
# Only do something if the interface actually exist
|
|
if _exists; then
|
|
ip -4 route flush table cache dev "${IFACE}"
|
|
fi
|
|
fi
|
|
|
|
# Kernel may not have IPv6 built in
|
|
if [ -e /proc/net/ipv6_route ]; then
|
|
local rules="$(service_get_value "ip6_rule")"
|
|
if [ -n "${rules}" ]; then
|
|
einfo "Removing IPv6 RPDB rules"
|
|
_ip_rule_runner -6 del "${rules}"
|
|
fi
|
|
|
|
# Only do something if the interface actually exist
|
|
if _exists; then
|
|
ip -6 route flush table cache dev "${IFACE}"
|
|
fi
|
|
fi
|
|
|
|
# Don't delete sit0 as it's a special tunnel
|
|
if [ "${IFACE}" != "sit0" ]; then
|
|
if [ -n "$(ip tunnel show "${IFACE}" 2>/dev/null)" ]; then
|
|
ebegin "Destroying tunnel ${IFACE}"
|
|
ip tunnel del "${IFACE}"
|
|
eend $?
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Is the interface administratively/operationally up?
|
|
# The 'UP' status in ifconfig/iproute2 is the administrative status
|
|
# Operational state is available in iproute2 output as 'state UP', or the
|
|
# operstate sysfs variable.
|
|
# 0: up
|
|
# 1: down
|
|
# 2: invalid arguments
|
|
is_admin_up()
|
|
{
|
|
local iface="$1"
|
|
[ -z "$iface" ] && iface="$IFACE"
|
|
ip link show dev $iface | \
|
|
sed -n '1,1{ /[<,]UP[,>]/{ q 0 }}; q 1; '
|
|
}
|
|
|
|
is_oper_up()
|
|
{
|
|
local iface="$1"
|
|
[ -z "$iface" ] && iface="$IFACE"
|
|
read state </sys/class/net/"${iface}"/operstate
|
|
[ "x$state" = "up" ]
|
|
}
|