diff options
Diffstat (limited to 'net/iproute2.sh')
-rw-r--r-- | net/iproute2.sh | 107 |
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 |