2009-05-01 15:11:40 +01:00
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
2011-06-29 19:46:31 -04:00
# Released under the 2-clause BSD license.
2007-11-14 15:22:04 +00:00
2008-01-11 15:08:57 +00:00
iproute2_depend( )
{
2012-01-08 16:24:03 -08:00
program ip
2007-04-05 11:18:42 +00:00
provide interface
after ifconfig
}
2008-01-11 15:08:57 +00:00
_up( )
{
2012-10-10 00:07:26 +00:00
ip link set dev " ${ IFACE } " up
2007-04-05 11:18:42 +00:00
}
2008-01-11 15:08:57 +00:00
_down( )
{
2012-10-10 00:07:26 +00:00
ip link set dev " ${ IFACE } " down
2007-04-05 11:18:42 +00:00
}
2008-01-11 15:08:57 +00:00
_exists( )
{
2012-03-02 19:54:48 +00:00
[ -e /sys/class/net/" $IFACE " ]
2007-04-05 11:18:42 +00:00
}
2008-01-11 15:08:57 +00:00
_ifindex( )
{
2012-04-01 22:59:00 -05:00
local index = -1
local f v
if [ -e /sys/class/net/" ${ IFACE } " /ifindex ] ; then
index = $( cat /sys/class/net/" ${ IFACE } " /ifindex)
else
for f in /sys/class/net/*/ifindex ; do
v = $( cat $f )
[ $v -gt $index ] && index = $v
2012-04-24 03:50:10 +02:00
done
2012-04-01 22:59:00 -05:00
: $(( index += 1 ))
fi
echo " ${ index } "
return 0
2007-04-05 11:18:42 +00:00
}
2008-01-11 15:08:57 +00:00
_is_wireless( )
{
2007-04-05 11:18:42 +00:00
# Support new sysfs layout
2009-12-05 19:25:39 +00:00
[ -d /sys/class/net/" ${ IFACE } " /wireless -o \
-d /sys/class/net/" ${ IFACE } " /phy80211 ] && return 0
2007-04-05 11:18:42 +00:00
[ ! -e /proc/net/wireless ] && return 1
2007-04-16 12:56:43 +00:00
grep -Eq " ^[[:space:]]* ${ IFACE } : " /proc/net/wireless
2007-04-05 11:18:42 +00:00
}
2008-01-11 15:08:57 +00:00
_set_flag( )
{
2007-11-01 22:25:53 +00:00
local flag = $1 opt = "on"
if [ " ${ flag #- } " != " ${ flag } " ] ; then
flag = ${ flag #- }
opt = "off"
fi
2012-10-10 00:07:26 +00:00
ip link set dev " ${ IFACE } " " ${ flag } " " ${ opt } "
2007-11-01 22:25:53 +00:00
}
2008-01-11 15:08:57 +00:00
_get_mac_address( )
{
2007-04-10 10:33:44 +00:00
local mac = $( LC_ALL = C ip link show " ${ IFACE } " | sed -n \
-e 'y/abcdef/ABCDEF/' \
-e '/link\// s/^.*\<\(..:..:..:..:..:..\)\>.*/\1/p' )
case " ${ mac } " in
2007-11-28 15:45:03 +00:00
00:00:00:00:00:00) ; ;
44:44:44:44:44:44) ; ;
FF:FF:FF:FF:FF:FF) ; ;
"" ) ; ;
*) echo " ${ mac } " ; return 0; ;
2007-04-10 10:33:44 +00:00
esac
return 1
}
2008-01-11 15:08:57 +00:00
_set_mac_address( )
{
2012-10-10 00:07:26 +00:00
ip link set dev " ${ IFACE } " address " $1 "
2007-04-10 10:33:44 +00:00
}
2008-01-11 15:08:57 +00:00
_get_inet_addresses( )
{
2007-04-05 11:18:42 +00:00
LC_ALL = C ip -family inet addr show " ${ IFACE } " | \
sed -n -e 's/.*inet \([^ ]*\).*/\1/p'
}
2008-01-11 15:08:57 +00:00
_get_inet_address( )
{
2007-04-05 11:18:42 +00:00
set -- $( _get_inet_addresses)
[ $# = "0" ] && return 1
echo " $1 "
}
2008-01-11 15:08:57 +00:00
_add_address( )
{
2007-11-28 15:45:03 +00:00
if [ " $1 " = "127.0.0.1/8" -a " ${ IFACE } " = "lo" ] ; then
2007-04-05 11:18:42 +00:00
ip addr add " $@ " dev " ${ IFACE } " 2>/dev/null
return 0
fi
2012-01-12 20:38:31 -08:00
local x
2011-07-18 07:09:28 +00:00
local address netmask broadcast peer anycast label scope
local valid_lft preferred_lft home nodad
2011-12-21 07:44:53 +00:00
local confflaglist
2011-07-18 07:09:28 +00:00
address = " $1 " ; shift
while [ -n " $* " ] ; do
2012-01-12 20:38:31 -08:00
x = $1 ; shift
case " $x " in
netmask| ne*)
netmask = " / $( _netmask2cidr " $1 " ) " ; shift ; ;
broadcast| brd| br*)
broadcast = " $1 " ; shift ; ;
pointopoint| pointtopoint| peer| po*| pe*)
peer = " $1 " ; shift ; ;
anycast| label| scope| valid_lft| preferred_lft| a*| l*| s*| v*| pr*)
case $x in
a*) x = anycast ; ;
l*) x = label ; ;
s*) x = scope ; ;
v*) x = valid_lft ; ;
pr*) x = preferred_lft ; ;
esac
eval " $x = $1 " ; shift ; ;
home| nodad| h*| no*)
case $x in h*) x = home ; ; n*) x = nodad ; ; esac
2011-12-21 07:44:53 +00:00
# FIXME: If we need to reorder these, this will take more code
2012-01-12 20:38:31 -08:00
confflaglist = " ${ confflaglist } $x " ; ; ;
*)
ewarn " Unknown argument to config_ $IFACE : $x "
2011-07-18 07:09:28 +00:00
esac
done
2011-01-17 04:49:07 -05:00
2007-04-05 11:18:42 +00:00
# Always scope lo addresses as host unless specified otherwise
2007-11-28 15:45:03 +00:00
if [ " ${ IFACE } " = "lo" ] ; then
2011-12-21 07:44:53 +00:00
[ -z " $scope " ] && scope = "host"
2007-04-05 11:18:42 +00:00
fi
2011-12-09 20:49:26 -06:00
# figure out the broadcast address if it is not specified
2011-12-21 08:03:38 +00:00
# This must NOT be set for IPv6 addresses
2011-12-28 20:31:02 +00:00
if [ " ${ address #* : } " = " ${ address } " ] ; then
2011-12-21 08:03:38 +00:00
[ -z " $broadcast " ] && broadcast = "+"
elif [ -n " $broadcast " ] ; then
eerror "Broadcast keywords are not valid with IPv6 addresses"
return 1
fi
2011-12-09 20:49:26 -06:00
2011-12-21 07:44:53 +00:00
# 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
2011-07-18 07:09:28 +00:00
veinfo ip addr add " $@ "
ip addr add " $@ "
2007-04-05 11:18:42 +00:00
}
2008-01-11 15:08:57 +00:00
_add_route( )
{
2009-04-19 20:05:40 +00:00
local family =
if [ " $1 " = "-A" -o " $1 " = "-f" -o " $1 " = "-family" ] ; then
family = " -f $2 "
shift; shift
2011-12-13 00:43:18 -08:00
elif [ " $1 " = "-4" ] ; then
family = "-f inet"
shift
elif [ " $1 " = "-6" ] ; then
family = "-f inet6"
shift
2009-04-19 20:05:40 +00:00
fi
2007-11-28 15:45:03 +00:00
if [ $# -eq 3 ] ; then
2007-04-05 11:18:42 +00:00
set -- " $1 " " $2 " via " $3 "
2007-11-28 15:45:03 +00:00
elif [ " $3 " = "gw" ] ; then
2007-04-05 11:18:42 +00:00
local one = $1 two = $2
2007-11-28 15:45:03 +00:00
shift; shift; shift
2007-12-31 09:26:53 +00:00
set -- " ${ one } " " ${ two } " via " $@ "
2007-04-05 11:18:42 +00:00
fi
2011-01-17 04:49:07 -05:00
local cmd = have_metric = false
2007-11-28 15:45:03 +00:00
while [ -n " $1 " ] ; do
2007-04-05 11:18:42 +00:00
case " $1 " in
2007-11-28 15:45:03 +00:00
metric) cmd = " ${ cmd } $1 " ; have_metric = true; ;
netmask) cmd = " ${ cmd } / $( _netmask2cidr " $2 " ) " ; shift; ;
-host| -net) ; ;
*) cmd = " ${ cmd } $1 " ; ;
2007-04-05 11:18:42 +00:00
esac
shift
done
2009-06-01 20:06:56 +01:00
# We cannot use a metric if we're using a nexthop
if ! ${ have_metric } && \
2010-07-07 19:55:37 -05:00
[ -n " ${ metric } " -a \
" ${ cmd ##* nexthop } " = " $cmd " ]
2009-06-01 20:06:56 +01:00
then
2007-04-05 11:18:42 +00:00
cmd = " ${ cmd } metric ${ metric } "
fi
2010-12-15 13:02:04 -08:00
veinfo ip ${ family } route append ${ cmd } dev " ${ IFACE } "
2009-04-19 20:05:40 +00:00
ip ${ family } route append ${ cmd } dev " ${ IFACE } "
2007-04-05 11:18:42 +00:00
eend $?
}
2008-01-11 15:08:57 +00:00
_delete_addresses( )
{
2007-04-05 11:18:42 +00:00
ip addr flush dev " ${ IFACE } " scope global 2>/dev/null
ip addr flush dev " ${ IFACE } " scope site 2>/dev/null
2007-11-28 15:45:03 +00:00
if [ " ${ IFACE } " != "lo" ] ; then
2007-04-05 11:18:42 +00:00
ip addr flush dev " ${ IFACE } " scope host 2>/dev/null
fi
return 0
}
2008-01-11 15:08:57 +00:00
_has_carrier( )
{
2012-09-07 14:29:56 -05:00
LC_ALL = C ip link show dev " ${ IFACE } " | grep -q "LOWER_UP"
2007-04-05 11:18:42 +00:00
}
2008-01-11 15:08:57 +00:00
_tunnel( )
{
2007-04-05 11:18:42 +00:00
ip tunnel " $@ "
}
2010-12-11 13:43:52 -08:00
# 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( ) {
2011-12-13 00:17:22 -08:00
local cmd rules OIFS = " ${ IFS } " family
2011-12-13 00:43:18 -08:00
if [ " $1 " = "-4" -o " $1 " = "-6" ] ; then
2011-12-13 00:17:22 -08:00
family = " $1 "
shift
else
family = "-4"
fi
2010-12-11 13:43:52 -08:00
cmd = " $1 "
rules = " $2 "
2010-12-15 13:02:04 -08:00
veindent
2010-12-11 13:43:52 -08:00
local IFS = " $__IFS "
for ru in $rules ; do
unset IFS
2011-02-12 13:34:46 -06:00
ruN = " $( _trim " ${ ru } " ) "
2010-12-11 13:43:52 -08:00
[ -z " ${ ruN } " ] && continue
2010-12-15 13:02:04 -08:00
vebegin " ${ cmd } ${ ruN } "
2011-12-13 00:17:22 -08:00
ip $family rule ${ cmd } ${ ru }
2010-12-15 13:02:04 -08:00
veend $?
2010-12-11 13:43:52 -08:00
local IFS = " $__IFS "
done
IFS = " ${ OIFS } "
2010-12-15 13:02:04 -08:00
veoutdent
2010-12-11 13:43:52 -08:00
}
2008-01-11 15:08:57 +00:00
iproute2_pre_start( )
{
2007-04-05 11:18:42 +00:00
local tunnel =
eval tunnel = \$ iptunnel_${ IFVAR }
2007-11-28 15:45:03 +00:00
if [ -n " ${ tunnel } " ] ; then
2007-04-05 11:18:42 +00:00
# Set our base metric to 1000
metric = 1000
2011-02-21 09:53:51 +00:00
# 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'
2007-04-05 11:18:42 +00:00
ebegin " Creating tunnel ${ IFVAR } "
2011-02-21 09:53:51 +00:00
ip ${ ipproto } tunnel add ${ tunnel } name " ${ IFACE } "
2007-04-05 11:18:42 +00:00
eend $? || return 1
2010-12-11 13:43:52 -08:00
_up
2007-04-05 11:18:42 +00:00
fi
2009-07-08 22:38:48 +01:00
# MTU support
local mtu =
eval mtu = \$ mtu_${ IFVAR }
2012-10-10 00:07:26 +00:00
[ -n " ${ mtu } " ] && ip link set dev " ${ IFACE } " mtu " ${ mtu } "
2009-07-08 22:38:48 +01:00
# TX Queue Length support
local len =
eval len = \$ txqueuelen_${ IFVAR }
2012-10-10 00:07:26 +00:00
[ -n " ${ len } " ] && ip link set dev " ${ IFACE } " txqueuelen " ${ len } "
2009-07-08 22:38:48 +01:00
2007-04-05 11:18:42 +00:00
return 0
}
2008-01-11 15:08:57 +00:00
_iproute2_ipv6_tentative( )
{
2008-05-27 16:41:53 +00:00
# Only check tentative when we have a carrier.
2012-09-07 14:29:56 -05:00
_has_carrier || return 1
2008-01-11 15:08:57 +00:00
LC_ALL = C ip addr show dev " ${ IFACE } " | \
2007-12-04 09:55:59 +00:00
grep -q "^[[:space:]]*inet6 .* tentative"
}
2008-01-11 15:08:57 +00:00
iproute2_post_start( )
{
2009-09-04 13:23:35 +01:00
local n = 5
2007-11-02 07:26:51 +00:00
# Kernel may not have IP built in
if [ -e /proc/net/route ] ; then
2010-12-11 13:43:52 -08:00
local rules = " $( _get_array " rules_ ${ IFVAR } " ) "
if [ -n " ${ rules } " ] ; then
2011-12-13 00:17:22 -08:00
if ! ip -4 rule list | grep -q "^" ; then
2010-12-11 13:43:52 -08:00
eerror "IP Policy Routing (CONFIG_IP_MULTIPLE_TABLES) needed for ip rule"
else
service_set_value "ip_rule" " ${ rules } "
2011-12-13 00:17:22 -08:00
einfo "Adding IPv4 RPDB rules"
_ip_rule_runner -4 add " ${ rules } "
2010-12-11 13:43:52 -08:00
fi
fi
2011-12-13 00:17:22 -08:00
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 } "
2007-11-02 07:26:51 +00:00
fi
2007-12-03 18:02:57 +00:00
2007-12-04 09:55:59 +00:00
if _iproute2_ipv6_tentative; then
ebegin "Waiting for IPv6 addresses"
2009-09-04 13:23:35 +01:00
while [ $n -ge 0 ] ; do
2007-12-04 09:55:59 +00:00
_iproute2_ipv6_tentative || break
2009-09-04 13:23:35 +01:00
sleep 1
2011-11-10 21:46:08 -05:00
: $(( n - = 1 ))
2007-12-04 09:55:59 +00:00
done
2009-09-04 13:23:35 +01:00
[ $n -ge 0 ]
eend $?
2007-12-04 09:55:59 +00:00
fi
2009-09-04 13:23:35 +01:00
return 0
2007-04-05 11:18:42 +00:00
}
2008-01-11 15:08:57 +00:00
iproute2_post_stop( )
{
2010-12-11 13:43:52 -08:00
# Kernel may not have IP built in
if [ -e /proc/net/route ] ; then
local rules = " $( service_get_value "ip_rule" ) "
2010-12-15 13:02:04 -08:00
if [ -n " ${ rules } " ] ; then
2011-12-13 00:17:22 -08:00
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
2011-12-26 17:51:28 -08:00
2011-12-13 00:17:22 -08:00
# 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 } "
2010-12-15 13:02:04 -08:00
fi
2011-09-21 03:57:09 +02:00
# Only do something if the interface actually exist
if _exists; then
2011-12-13 00:17:22 -08:00
ip -6 route flush table cache dev " ${ IFACE } "
2011-09-21 03:57:09 +02:00
fi
2010-12-11 13:43:52 -08:00
fi
2007-04-05 11:18:42 +00:00
# Don't delete sit0 as it's a special tunnel
2007-11-28 15:45:03 +00:00
if [ " ${ IFACE } " != "sit0" ] ; then
if [ -n " $( ip tunnel show " ${ IFACE } " 2>/dev/null) " ] ; then
2007-04-05 11:18:42 +00:00
ebegin " Destroying tunnel ${ IFACE } "
2008-05-25 22:34:05 +00:00
ip tunnel del " ${ IFACE } "
2007-04-05 11:18:42 +00:00
eend $?
fi
fi
}
2011-12-12 18:48:11 -08:00
# 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" ]
}