diff --git a/net/iproute2.sh b/net/iproute2.sh index b7152d9..f9b493b 100644 --- a/net/iproute2.sh +++ b/net/iproute2.sh @@ -204,6 +204,31 @@ _add_address() return $rc } +_filter_metric() +{ + # ip route show does not allow to filter by metric + # so we need to filter metric manually + + local metric_value="$1" + shift + + if [ "${metric_value}" -eq 0 ]; then + # metric 0 is not displayed + ip -o "$@" | fgrep -vsq " metric " + else + # add trailing space for matching + echo "$(ip -o "$@") " | fgrep -sq " metric ${metric_value} " + fi +} + +_is_route_type() +{ + case "$1" in + unicast|multicast|local|broadcast|throw|unreachable|prohibit|blackhole) true ;; + *) false ;; + esac +} + _add_route() { local family= @@ -219,41 +244,93 @@ _add_route() shift fi - if [ $# -eq 3 ]; then + if _is_route_type "$2"; then + : + elif [ $# -eq 3 ]; then set -- "$1" "$2" via "$3" elif [ "$3" = "gw" ]; then - local one=$1 two=$2 + local one="$1" two="$2" shift; shift; shift set -- "${one}" "${two}" via "$@" fi - local cmd_add= cmd_show= have_metric=false + local cmd_prefix= cmd_add= cmd_show= metric_value= table_value= + local have_metric=false have_table=false have_prefix=false nodev=false while [ -n "$1" ]; do case "$1" in - metric) metric=$2 ; cmd_add="${cmd_add} metric $2" ; shift ; have_metric=true ;; - netmask) x="/$(_netmask2cidr "$2")" ; cmd_add="${cmd_add}${x}" ; cmd_show="${cmd_show}${x}" ; shift;; + metric|preference) + metric="$2" + cmd_prefix="${cmd_prefix} ${1} ${2}" + metric_value="$2" + have_metric=true + shift ;; + netmask) + x="/$(_netmask2cidr "$2")" + cmd_prefix="${cmd_prefix}${x}" + cmd_show="${cmd_show}${x}" + have_prefix=true + shift ;; + tos) + cmd_add="${cmd_add} ${1} ${2}" + cmd_show="${cmd_show} ${1} ${2}" + shift ;; + table) + cmd_add="${cmd_add} ${1} ${2}" + cmd_show="${cmd_show} ${1} ${2}" + have_table=true + shift ;; + unicast|multicast) + cmd_prefix="${cmd_prefix} ${1}" + ;; + local|broadcast) + # those are added to table local by default + cmd_prefix="${cmd_prefix} ${1}" + table_value="local" + ;; + throw|unreachable|prohibit|blackhole) + cmd_prefix="${cmd_prefix} ${1}" + nodev=true + ;; -host|-net);; - *) cmd_add="${cmd_add} ${1}" ; cmd_show="${cmd_show} ${1}" ;; + *) + if ${have_prefix}; then + cmd_add="${cmd_add} ${1}" + else + cmd_prefix="${cmd_prefix} ${1}" + cmd_show="${cmd_show} ${1}" + have_prefix=true + fi ;; esac shift done - # We cannot use a metric if we're using a nexthop - if ! ${have_metric} && \ - [ -n "${metric}" -a \ - "${cmd_add##* nexthop }" = "${cmd_add}" ] - then - cmd_add="${cmd_add} metric ${metric}" + # Add table for special types + if ! ${have_table} && [ -n "${table_value}" ]; then + cmd_show="${cmd_show} table ${table_value}" + fi + + # Add interface's metric by default + if ! ${have_metric} && [ -n "${metric}" ]; then + cmd_prefix="${cmd_prefix} metric ${metric}" + metric_value="${metric}" fi # Check for route already existing: - ip ${family} route show ${cmd_show} dev "${IFACE}" 2>/dev/null | \ - fgrep -sq "${cmd_add%% *}" + _filter_metric "${metric_value}" ${family} route show ${cmd_show} 2>/dev/null route_already_exists=$? - veinfo ip ${family} route append ${cmd_add} dev "${IFACE}" - ip ${family} route append ${cmd_add} dev "${IFACE}" - rc=$? + cmd_add="${cmd_prefix}${cmd_add}" + + if yesno "${nodev}"; then + veinfo ip ${family} route append ${cmd_add} + ip ${family} route append ${cmd_add} + rc=$? + else + veinfo ip ${family} route append ${cmd_add} dev "${IFACE}" + ip ${family} route append ${cmd_add} dev "${IFACE}" + rc=$? + fi + # Check return code in some cases if [ $rc -ne 0 ]; then # If the route already exists, our default behavior is to WARN but continue. @@ -268,7 +345,7 @@ _add_route() *) msgfunc=eerror rc=1 ; eerror "Unknown error behavior: $eh_behavior" ;; esac eval $msgfunc "Route '$cmd_show' already existed:" - eval $msgfunc \"$(ip $family route show ${cmd_show} dev "${IFACE}" 2>&1)\" + eval $msgfunc "\"$(_filter_metric "${metric_value}" $family route show ${cmd_show} 2>&1)\"" else : # TODO: Handle other errors fi