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