aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'net/iproute2.sh')
-rw-r--r--net/iproute2.sh107
1 files changed, 91 insertions, 16 deletions
diff --git a/net/iproute2.sh b/net/iproute2.sh
index d74bc29..32d3c88 100644
--- a/net/iproute2.sh
+++ b/net/iproute2.sh
@@ -109,13 +109,32 @@ _add_address()
local x
local address netmask broadcast peer anycast label scope
local valid_lft preferred_lft home nodad
- local confflaglist
- address="$1" ; shift
+ local confflaglist family raw_address family_maxnetmask
+ raw_address="$1" ; shift
+ # Extract the netmask on address if present.
+ if [ "${raw_address%\/*}" != "${raw_address}" ]; then
+ address="${raw_address%\/*}"
+ netmask="${raw_address#*\/}"
+ else
+ address="$raw_address"
+ fi
+
+ # Some options are not valid for one family or the other.
+ case ${address} in
+ *:*) family=6 family_maxnetmask=128 ;;
+ *) family=4 family_maxnetmask=32 ;;
+ esac
+
while [ -n "$*" ]; do
x=$1 ; shift
case "$x" in
netmask|ne*)
- netmask="/$(_netmask2cidr "$1")" ; shift ;;
+ if [ -n "${netmask}" ]; then
+ eerror "Too many netmasks: $raw_address netmask $1"
+ return 1
+ fi
+ netmask="/$(_netmask2cidr "$1")"
+ shift ;;
broadcast|brd|br*)
broadcast="$1" ; shift ;;
pointopoint|pointtopoint|peer|po*|pe*)
@@ -150,17 +169,44 @@ _add_address()
# 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
+ case $family in
+ 4) [ -z "$broadcast" ] && broadcast="+" ;;
+ 6) [ -n "$broadcast" ] && eerror "Broadcast keywords are not valid with IPv6 addresses" && return 1 ;;
+ esac
+
+ # Always have a netmask
+ [ -z "$netmask" ] && netmask=$family_maxnetmask
+
+ # Check for address already existing:
+ ip addr show to "${address}/${family_maxnetmask}" dev "${IFACE}" 2>/dev/null | \
+ fgrep -sq "${address}"
+ address_already_exists=$?
# 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
+ set -- "${address}${netmask:+/}${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 "$@"
+ rc=$?
+ # Check return code in some cases
+ if [ $rc -ne 0 ]; then
+ # If the address already exists, our default behavior is to WARN but continue.
+ # You can completely silence this with: errh_IFVAR_address_EEXIST=continue
+ if [ $address_already_exists -eq 0 ]; then
+ eh_behavior=$(_get_errorhandler_behavior "$IFVAR" "address" "EEXIST" "warn")
+ case $eh_behavior in
+ continue) msgfunc=true rc=0 ;;
+ info) msgfunc=einfo rc=0 ;;
+ warn) msgfunc=ewarn rc=0 ;;
+ error|fatal) msgfunc=eerror rc=1;;
+ *) msgfunc=eerror rc=1 ; eerror "Unknown error behavior: $eh_behavior" ;;
+ esac
+ eval $msgfunc "Address ${address}${netmask:+/}${netmask} already existed!"
+ eval $msgfunc \"$(ip addr show to "${address}/${family_maxnetmask}" dev "${IFACE}" 2>&1)\"
+ else
+ : # TODO: Handle other errors
+ fi
+ fi
+ return $rc
}
_add_route()
@@ -186,13 +232,13 @@ _add_route()
set -- "${one}" "${two}" via "$@"
fi
- local cmd= have_metric=false
+ local cmd= cmd_nometric= have_metric=false
while [ -n "$1" ]; do
case "$1" in
- metric) cmd="${cmd} $1"; have_metric=true;;
- netmask) cmd="${cmd}/$(_netmask2cidr "$2")"; shift;;
+ metric) metric=$2 ; cmd="${cmd} metric $2" ; shift ; have_metric=true ;;
+ netmask) x="/$(_netmask2cidr "$2")" ; cmd="${cmd}${x}" ; cmd_nometric="${cmd}${x}" ; shift;;
-host|-net);;
- *) cmd="${cmd} $1";;
+ *) cmd="${cmd} ${1}" ; cmd_nometric="${cmd_nometric} ${1}" ;;
esac
shift
done
@@ -205,9 +251,34 @@ _add_route()
cmd="${cmd} metric ${metric}"
fi
+ # Check for route already existing:
+ ip ${family} route show ${cmd_nometric} dev "${IFACE}" 2>/dev/null | \
+ fgrep -sq "${cmd%% *}"
+ route_already_exists=$?
+
veinfo ip ${family} route append ${cmd} dev "${IFACE}"
ip ${family} route append ${cmd} dev "${IFACE}"
- eend $?
+ rc=$?
+ # Check return code in some cases
+ if [ $rc -ne 0 ]; then
+ # If the route already exists, our default behavior is to WARN but continue.
+ # You can completely silence this with: errh_IFVAR_route_EEXIST=continue
+ if [ $route_already_exists -eq 0 ]; then
+ eh_behavior=$(_get_errorhandler_behavior "$IFVAR" "route" "EEXIST" "warn")
+ case $eh_behavior in
+ continue) msgfunc=true rc=0 ;;
+ info) msgfunc=einfo rc=0 ;;
+ warn) msgfunc=ewarn rc=0 ;;
+ error|fatal) msgfunc=eerror rc=1;;
+ *) msgfunc=eerror rc=1 ; eerror "Unknown error behavior: $eh_behavior" ;;
+ esac
+ eval $msgfunc "Route '$cmd_nometric' already existed:"
+ eval $msgfunc \"$(ip $family route show ${cmd_nometric} dev "${IFACE}" 2>&1)\"
+ else
+ : # TODO: Handle other errors
+ fi
+ fi
+ eend $rc
}
_delete_addresses()
@@ -232,6 +303,9 @@ _tunnel()
{
veinfo ip tunnel "$@"
ip tunnel "$@"
+ rc=$?
+ # TODO: check return code in some cases
+ return $rc
}
# This is just to trim whitespace, do not add any quoting!
@@ -367,6 +441,8 @@ iproute2_post_start()
[ -z "$policyroute_order" ] && policyroute_order=${policy_rules_before_routes:-no}
yesno "$policyroute_order" || _iproute2_policy_routing
+ # This block must be non-fatal, otherwise the interface will not be
+ # recorded as starting, and later services may be blocked.
if _iproute2_ipv6_tentative; then
einfon "Waiting for IPv6 addresses (${_dad_timeout} seconds) "
while [ $_dad_timeout -gt 0 ]; do
@@ -380,7 +456,6 @@ iproute2_post_start()
if [ $_dad_timeout -le 0 ]; then
eend 1
- return 1
else
eend 0
fi