3 promote_secondaries=true
7 echo "ip stub command: \"$1\" not implemented"
11 ######################################################################
20 up) ip_link_set_up "$1" ;;
21 down) ip_link_down_up "$1" ;;
22 *) not_implemented "\"$2\" in \"$orig_args\"" ;;
25 show) shift ; ip_link_show "$@" ;;
26 add*) shift ; ip_link_add "$@" ;;
27 del*) shift ; ip_link_delete "$@" ;;
28 *) not_implemented "$*" ;;
38 while [ -n "$1" ] ; do
49 if [ "$2" != "vlan" ] ; then
50 not_implemented "link type $1"
56 *) not_implemented "$1" ;;
62 if [ -z "$_name" -o -z "$_link" ] ; then
63 not_implemented "ip link add with null name or link"
66 mkdir -p "${FAKE_IP_STATE}/interfaces-vlan"
67 echo "$_link" >"${FAKE_IP_STATE}/interfaces-vlan/${_name}"
68 ip_link_set_down "$_name"
75 mkdir -p "${FAKE_IP_STATE}/interfaces-deleted"
76 touch "${FAKE_IP_STATE}/interfaces-deleted/$1"
77 rm -f "${FAKE_IP_STATE}/interfaces-vlan/$1"
82 rm -f "${FAKE_IP_STATE}/interfaces-down/$1"
83 rm -f "${FAKE_IP_STATE}/interfaces-deleted/$1"
88 rm -f "${FAKE_IP_STATE}/interfaces-deleted/$1"
89 mkdir -p "${FAKE_IP_STATE}/interfaces-down"
90 touch "${FAKE_IP_STATE}/interfaces-down/$1"
96 if [ "$dev" = "dev" -a -n "$2" ] ; then
100 if [ -e "${FAKE_IP_STATE}/interfaces-deleted/$dev" ] ; then
101 echo "Device \"${dev}\" does not exist." >&2
105 if [ -r "${FAKE_IP_STATE}/interfaces-vlan/${dev}" ] ; then
106 read _link <"${FAKE_IP_STATE}/interfaces-vlan/${dev}"
107 dev="${dev}@${_link}"
110 mac=$(echo $dev | md5sum | sed -r -e 's@(..)(..)(..)(..)(..)(..).*@\1:\2:\3:\4:\5:\6@')
112 _flags=",UP,LOWER_UP"
113 if [ -e "${FAKE_IP_STATE}/interfaces-down/$dev" ] ; then
117 echo "${n:-42}: ${dev}: <BROADCAST,MULTICAST${_flags}> mtu 1500 qdisc pfifo_fast state ${_state} qlen 1000"
118 echo " link/ether ${mac} brd ff:ff:ff:ff:ff:ff"
121 # This is incomplete because it doesn't actually look up table ids in
122 # /etc/iproute2/rt_tables. The rules/routes are actually associated
123 # with the name instead of the number. However, we include a variable
124 # to fake a bad table id.
125 [ -n "$IP_ROUTE_BAD_TABLE_ID" ] || IP_ROUTE_BAD_TABLE_ID=false
131 if [ "$_cmd" = "route" -a -z "$_table" ] ;then
135 [ -n "$_table" ] || not_implemented "ip rule/route without \"table\""
137 # Only allow tables names from 13.per_ip_routing and "main". This
138 # is a cheap way of avoiding implementing the default/local
142 if $IP_ROUTE_BAD_TABLE_ID ; then
143 # Ouch. Simulate inconsistent errors from ip. :-(
146 echo "Error: argument "${_table}" is wrong: table id value is invalid" >&2
150 echo "Error: argument "${_table}" is wrong: invalid table ID" >&2
155 *) not_implemented "table=${_table} ${orig_args}" ;;
159 ######################################################################
164 show|list|"") shift ; ip_addr_show "$@" ;;
165 add*) shift ; ip_addr_add "$@" ;;
166 del*) shift ; ip_addr_del "$@" ;;
167 *) not_implemented "\"$1\" in \"$orig_args\"" ;;
177 while [ -n "$1" ] ; do
182 # Do stupid things and stupid things will happen!
184 primary=true ; secondary=false ; shift
187 secondary=true ; primary=false ; shift
193 # Assume an interface name
198 if [ -z "$devices" ] ; then
199 # No device specified? Get all the primaries...
200 devices=$(ls "${FAKE_IP_STATE}/addresses/"*-primary 2>/dev/null | \
201 sed -e 's@.*/@@' -e 's@-.*-primary$@@' | sort -u)
205 case "${local#*/}" in
207 brd="${local%.*}.255"
210 not_implemented "list ... fake bits other than 24: ${local#*/}"
217 nets=$(ls "${FAKE_IP_STATE}/addresses/${dev}"-*-primary 2>/dev/null | \
218 sed -e 's@.*/@@' -e "s@${dev}-\(.*\)-primary\$@\1@")
220 for net in $nets ; do
221 pf="${FAKE_IP_STATE}/addresses/${dev}-${net}-primary"
222 sf="${FAKE_IP_STATE}/addresses/${dev}-${net}-secondary"
223 if $primary && [ -r "$pf" ] ; then
225 if [ -z "$_to" -o "${_to%/*}" = "${local%/*}" ] ; then
227 echo " inet ${local} brd ${brd} scope global ${dev}"
230 if $secondary && [ -r "$sf" ] ; then
231 while read local ; do
232 if [ -z "$_to" -o "${_to%/*}" = "${local%/*}" ] ; then
234 echo " inet ${local} brd ${brd} scope global secondary ${dev}"
238 if [ -z "$_to" ] ; then
239 echo " valid_lft forever preferred_lft forever"
244 for dev in $devices ; do
245 if [ -z "$_to" ] || \
246 grep -F "${_to%/*}/" "${FAKE_IP_STATE}/addresses/${dev}-"* >/dev/null ; then
253 # Copied from 13.per_ip_routing for now... so this is lazy testing :-(
254 ipv4_host_addr_to_net ()
259 # Convert the host address to an unsigned long by splitting out
260 # the octets and doing the math.
262 for _o in $(export IFS="." ; echo $_host) ; do
263 _host_ul=$(( ($_host_ul << 8) + $_o)) # work around Emacs color bug
266 # Calculate the mask and apply it.
267 _mask_ul=$(( 0xffffffff << (32 - $_maskbits) ))
268 _net_ul=$(( $_host_ul & $_mask_ul ))
270 # Now convert to a network address one byte at a time.
272 for _o in $(seq 1 4) ; do
273 _net="$(($_net_ul & 255))${_net:+.}${_net}"
274 _net_ul=$(($_net_ul >> 8))
277 echo "${_net}/${_maskbits}"
285 while [ -n "$1" ] ; do
294 # For now assume this is always '+'.
295 if [ "$2" != "+" ] ; then
296 not_implemented "addr add ... brd $2 ..."
307 if [ -z "$dev" ] ; then
308 not_implemented "addr add (without dev)"
310 mkdir -p "${FAKE_IP_STATE}/addresses"
311 net_str=$(ipv4_host_addr_to_net $(IFS="/" ; echo $local))
312 net_str=$(echo "$net_str" | sed -e 's@/@_@')
313 pf="${FAKE_IP_STATE}/addresses/${dev}-${net_str}-primary"
314 sf="${FAKE_IP_STATE}/addresses/${dev}-${net_str}-secondary"
315 # We could lock here... but we should be the only ones playing
316 # around here with these stubs.
317 if [ ! -f "$pf" ] ; then
319 elif grep -Fq "$local" "$pf" ; then
320 echo "RTNETLINK answers: File exists" >&2
322 elif [ -f "$sf" ] && grep -Fq "$local" "$sf" ; then
323 echo "RTNETLINK answers: File exists" >&2
326 echo "$local" >>"$sf"
334 while [ -n "$1" ] ; do
346 not_implemented "addr del ... $1 ..."
349 if [ -z "$dev" ] ; then
350 not_implemented "addr del (without dev)"
352 mkdir -p "${FAKE_IP_STATE}/addresses"
353 net_str=$(ipv4_host_addr_to_net $(IFS="/" ; echo $local))
354 net_str=$(echo "$net_str" | sed -e 's@/@_@')
355 pf="${FAKE_IP_STATE}/addresses/${dev}-${net_str}-primary"
356 sf="${FAKE_IP_STATE}/addresses/${dev}-${net_str}-secondary"
357 # We could lock here... but we should be the only ones playing
358 # around here with these stubs.
359 if [ ! -f "$pf" ] ; then
360 echo "RTNETLINK answers: Cannot assign requested address" >&2
362 elif grep -Fq "$local" "$pf" ; then
363 if $promote_secondaries && [ -s "$sf" ] ; then
364 head -n 1 "$sf" >"$pf"
367 # Remove primaries AND SECONDARIES.
370 elif [ -f "$sf" ] && grep -Fq "$local" "$sf" ; then
371 grep -Fv "$local" "$sf" >"${sf}.new"
374 echo "RTNETLINK answers: Cannot assign requested address" >&2
379 ######################################################################
384 show|list|"") shift ; ip_rule_show "$@" ;;
385 add) shift ; ip_rule_add "$@" ;;
386 del*) shift ; ip_rule_del "$@" ;;
387 *) not_implemented "$1 in \"$orig_args\"" ;;
392 # All non-default rules are in $FAKE_IP_STATE_RULES/rules. As with
393 # the real version, rules can be repeated. Deleting just deletes the
403 # potentially more options
405 printf "%d:\t%s lookup %s \n" $_pre "$_selectors" "$_table"
413 [ -f "${FAKE_IP_STATE}/rules" ] || return
415 while read _pre _table _selectors ; do
416 # Only print those in range
417 [ $_min -le $_pre -a $_pre -le $_max ] || continue
419 ip_rule_show_1 $_pre "$_table" "$_selectors"
420 done <"${FAKE_IP_STATE}/rules"
423 ip_rule_show_1 0 "local" "from all"
425 ip_rule_show_some 1 32765
427 ip_rule_show_1 32766 "main" "from all"
428 ip_rule_show_1 32767 "default" "from all"
430 ip_rule_show_some 32768 2147483648
438 while [ -n "$1" ] ; do
440 from) _from="$2" ; shift 2 ;;
441 pref) _pre="$2" ; shift 2 ;;
442 table) _table="$2" ; shift 2 ;;
443 *) not_implemented "$1 in \"$orig_args\"" ;;
447 [ -n "$_pre" ] || not_implemented "ip rule without \"pref\""
448 ip_check_table "rule"
449 # Relax this if more selectors added later...
450 [ -n "$_from" ] || not_implemented "ip rule without \"from\""
457 _f="${FAKE_IP_STATE}/rules"
461 # Filter order must be consistent with the comparison in ip_rule_del()
462 echo "$_pre $_table${_from:+ from }$_from" >>"$_f"
470 _f="${FAKE_IP_STATE}/rules"
476 while read _p _t _s ; do
478 [ "$_p" = "$_pre" -a "$_t" = "$_table" -a \
479 "$_s" = "${_from:+from }$_from" ] ; then
480 # Found. Skip this one but not future ones.
483 echo "$_p $_t $_s" >>"$_tmp"
486 if cmp -s "$_tmp" "$_f" ; then
487 # No changes, must not have found what we wanted to delete
488 echo "RTNETLINK answers: No such file or directory" >&2
497 ######################################################################
502 show|list) shift ; ip_route_show "$@" ;;
503 flush) shift ; ip_route_flush "$@" ;;
504 add) shift ; ip_route_add "$@" ;;
505 del*) shift ; ip_route_del "$@" ;;
506 *) not_implemented "$1 in \"ip route\"" ;;
512 if [ "$1" = table ] ; then
517 ip_check_table "route"
520 # Routes are in a file per table in the directory
521 # $FAKE_IP_STATE/routes. These routes just use the table ID
522 # that is passed and don't do any lookup. This could be "improved" if
529 # Missing file is just an empty table
530 sort "$FAKE_IP_STATE/routes/${_table}" 2>/dev/null || true
537 rm -f "$FAKE_IP_STATE/routes/${_table}"
548 while [ -n "$1" ] ; do
550 *.*.*.*/*|*.*.*.*) _prefix="$1" ; shift 1 ;;
551 local) _prefix="$2" ; shift 2 ;;
552 dev) _dev="$2" ; shift 2 ;;
553 via) _gw="$2" ; shift 2 ;;
554 table) _table="$2" ; shift 2 ;;
555 metric) _metric="$2" ; shift 2 ;;
556 *) not_implemented "$1 in \"$orig_args\"" ;;
560 ip_check_table "route"
561 [ -n "$_prefix" ] || not_implemented "ip route without inet prefix in \"$orig_args\""
562 # This can't be easily deduced, so print some garbage.
563 [ -n "$_dev" ] || _dev="ethXXX"
565 # Alias or add missing bits
567 0.0.0.0/0) _prefix="default" ;;
569 *) _prefix="${_prefix}/32" ;;
572 _f="$FAKE_IP_STATE/routes/${_table}"
573 mkdir -p "$FAKE_IP_STATE/routes"
576 # Check for duplicate
577 _prefix_regexp=$(echo "^${_prefix}" | sed -e 's@\.@\\.@g')
578 if [ -n "$_metric" ] ; then
579 _prefix_regexp="${_prefix_regexp} .*metric ${_metric} "
581 if grep -q "$_prefix_regexp" "$_f" ; then
582 echo "RTNETLINK answers: File exists" >&2
590 [ -z "$_gw" ] || _out="${_out}via ${_gw} "
591 [ -z "$_dev" ] || _out="${_out}dev ${_dev} "
592 [ -n "$_gw" ] || _out="${_out} scope link "
593 [ -z "$_metric" ] || _out="${_out} metric ${_metric} "
606 while [ -n "$1" ] ; do
608 *.*.*.*/*|*.*.*.*) _prefix="$1" ; shift 1 ;;
609 local) _prefix="$2" ; shift 2 ;;
610 dev) _dev="$2" ; shift 2 ;;
611 via) _gw="$2" ; shift 2 ;;
612 table) _table="$2" ; shift 2 ;;
613 metric) _metric="$2" ; shift 2 ;;
614 *) not_implemented "$1 in \"$orig_args\"" ;;
618 ip_check_table "route"
619 [ -n "$_prefix" ] || not_implemented "ip route without inet prefix in \"$orig_args\""
620 # This can't be easily deduced, so print some garbage.
621 [ -n "$_dev" ] || _dev="ethXXX"
623 # Alias or add missing bits
625 0.0.0.0/0) _prefix="default" ;;
627 *) _prefix="${_prefix}/32" ;;
630 _f="$FAKE_IP_STATE/routes/${_table}"
631 mkdir -p "$FAKE_IP_STATE/routes"
638 [ -z "$_gw" ] || _gw=$(echo "$_gw" | sed -e 's@\.@\\.@g')
639 _prefix=$(echo "$_prefix" | sed -e 's@\.@\\.@g' -e 's@/@\\/@')
641 _re="^${_prefix}\>.*"
642 [ -z "$_gw" ] || _re="${_re}\<via ${_gw}\>.*"
643 [ -z "$_dev" ] || _re="${_re}\<dev ${_dev}\>.*"
644 [ -z "$_metric" ] || _re="${_re}.*\<metric ${_metric}\>.*"
645 sed -i -e "/${_re}/d" "$_f"
649 ######################################################################
654 link) shift ; ip_link "$@" ;;
655 addr*) shift ; ip_addr "$@" ;;
656 rule) shift ; ip_rule "$@" ;;
657 route) shift ; ip_route "$@" ;;
658 *) not_implemented "$1" ;;