3 FAKE_IP_STATE="${FAKE_NETWORK_STATE}/ip-state"
4 mkdir -p "$FAKE_IP_STATE"
6 promote_secondaries=true
10 echo "ip stub command: \"$1\" not implemented"
14 ######################################################################
23 up) ip_link_set_up "$1" ;;
24 down) ip_link_down_up "$1" ;;
25 *) not_implemented "\"$2\" in \"$orig_args\"" ;;
28 show) shift ; ip_link_show "$@" ;;
29 add*) shift ; ip_link_add "$@" ;;
30 del*) shift ; ip_link_delete "$@" ;;
31 *) not_implemented "$*" ;;
41 while [ -n "$1" ] ; do
52 if [ "$2" != "vlan" ] ; then
53 not_implemented "link type $1"
59 *) not_implemented "$1" ;;
65 if [ -z "$_name" -o -z "$_link" ] ; then
66 not_implemented "ip link add with null name or link"
69 mkdir -p "${FAKE_IP_STATE}/interfaces-vlan"
70 echo "$_link" >"${FAKE_IP_STATE}/interfaces-vlan/${_name}"
71 ip_link_set_down "$_name"
78 mkdir -p "${FAKE_IP_STATE}/interfaces-deleted"
79 touch "${FAKE_IP_STATE}/interfaces-deleted/$1"
80 rm -f "${FAKE_IP_STATE}/interfaces-vlan/$1"
85 rm -f "${FAKE_IP_STATE}/interfaces-down/$1"
86 rm -f "${FAKE_IP_STATE}/interfaces-deleted/$1"
91 rm -f "${FAKE_IP_STATE}/interfaces-deleted/$1"
92 mkdir -p "${FAKE_IP_STATE}/interfaces-down"
93 touch "${FAKE_IP_STATE}/interfaces-down/$1"
99 if [ "$dev" = "dev" -a -n "$2" ] ; then
103 if [ -e "${FAKE_IP_STATE}/interfaces-deleted/$dev" ] ; then
104 echo "Device \"${dev}\" does not exist." >&2
108 if [ -r "${FAKE_IP_STATE}/interfaces-vlan/${dev}" ] ; then
109 read _link <"${FAKE_IP_STATE}/interfaces-vlan/${dev}"
110 dev="${dev}@${_link}"
114 _flags=",UP,LOWER_UP"
115 if [ -e "${FAKE_IP_STATE}/interfaces-down/$dev" ] ; then
121 _mac="00:00:00:00:00:00"
122 _brd="00:00:00:00:00:00"
124 _opts="<LOOPBACK${_flags}> mtu 65536 qdisc noqueue state UNKNOWN"
127 _mac=$(echo $dev | md5sum | sed -r -e 's@(..)(..)(..)(..)(..)(..).*@\1:\2:\3:\4:\5:\6@')
128 _brd="ff:ff:ff:ff:ff:ff"
130 _opts="<BROADCAST,MULTICAST${_flags}> mtu 1500 qdisc pfifo_fast state ${_state} qlen 1000"
132 echo "${n:-42}: ${dev}: ${_opts}"
133 echo " link/${_type} ${_mac} brd ${_brd}"
136 # This is incomplete because it doesn't actually look up table ids in
137 # /etc/iproute2/rt_tables. The rules/routes are actually associated
138 # with the name instead of the number. However, we include a variable
139 # to fake a bad table id.
140 [ -n "$IP_ROUTE_BAD_TABLE_ID" ] || IP_ROUTE_BAD_TABLE_ID=false
146 if [ "$_cmd" = "route" -a -z "$_table" ] ;then
150 [ -n "$_table" ] || not_implemented "ip rule/route without \"table\""
152 # Only allow tables names from 13.per_ip_routing and "main". This
153 # is a cheap way of avoiding implementing the default/local
157 if $IP_ROUTE_BAD_TABLE_ID ; then
158 # Ouch. Simulate inconsistent errors from ip. :-(
161 echo "Error: argument "${_table}" is wrong: table id value is invalid" >&2
165 echo "Error: argument "${_table}" is wrong: invalid table ID" >&2
170 *) not_implemented "table=${_table} ${orig_args}" ;;
174 ######################################################################
179 show|list|"") shift ; ip_addr_show "$@" ;;
180 add*) shift ; ip_addr_add "$@" ;;
181 del*) shift ; ip_addr_del "$@" ;;
182 *) not_implemented "\"$1\" in \"$orig_args\"" ;;
192 while [ -n "$1" ] ; do
197 # Do stupid things and stupid things will happen!
199 primary=true ; secondary=false ; shift
202 secondary=true ; primary=false ; shift
208 # Assume an interface name
213 if [ -z "$devices" ] ; then
214 # No device specified? Get all the primaries...
215 devices=$(ls "${FAKE_IP_STATE}/addresses/"*-primary 2>/dev/null | \
216 sed -e 's@.*/@@' -e 's@-.*-primary$@@' | sort -u)
220 case "${local#*/}" in
221 24) brd="${local%.*}.255" ;;
223 *) not_implemented "list ... fake bits other than 24/32: ${local#*/}"
230 nets=$(ls "${FAKE_IP_STATE}/addresses/${dev}"-*-primary 2>/dev/null | \
231 sed -e 's@.*/@@' -e "s@${dev}-\(.*\)-primary\$@\1@")
233 for net in $nets ; do
234 pf="${FAKE_IP_STATE}/addresses/${dev}-${net}-primary"
235 sf="${FAKE_IP_STATE}/addresses/${dev}-${net}-secondary"
236 if $primary && [ -r "$pf" ] ; then
237 read local scope <"$pf"
238 if [ -z "$_to" -o "${_to%/*}" = "${local%/*}" ] ; then
240 echo " inet ${local} ${brd:+brd ${brd} }scope ${scope} ${dev}"
243 if $secondary && [ -r "$sf" ] ; then
244 while read local scope ; do
245 if [ -z "$_to" -o "${_to%/*}" = "${local%/*}" ] ; then
247 echo " inet ${local} ${brd:+brd }${brd} scope ${scope} secondary ${dev}"
251 if [ -z "$_to" ] ; then
252 echo " valid_lft forever preferred_lft forever"
257 for dev in $devices ; do
258 if [ -z "$_to" ] || \
259 grep -F "${_to%/*}/" "${FAKE_IP_STATE}/addresses/${dev}-"* >/dev/null ; then
266 # Copied from 13.per_ip_routing for now... so this is lazy testing :-(
267 ipv4_host_addr_to_net ()
272 # Convert the host address to an unsigned long by splitting out
273 # the octets and doing the math.
275 for _o in $(export IFS="." ; echo $_host) ; do
276 _host_ul=$(( ($_host_ul << 8) + $_o)) # work around Emacs color bug
279 # Calculate the mask and apply it.
280 _mask_ul=$(( 0xffffffff << (32 - $_maskbits) ))
281 _net_ul=$(( $_host_ul & $_mask_ul ))
283 # Now convert to a network address one byte at a time.
285 for _o in $(seq 1 4) ; do
286 _net="$(($_net_ul & 255))${_net:+.}${_net}"
287 _net_ul=$(($_net_ul >> 8))
290 echo "${_net}/${_maskbits}"
299 while [ -n "$1" ] ; do
308 # For now assume this is always '+'.
309 if [ "$2" != "+" ] ; then
310 not_implemented "addr add ... brd $2 ..."
324 if [ -z "$dev" ] ; then
325 not_implemented "addr add (without dev)"
327 mkdir -p "${FAKE_IP_STATE}/addresses"
328 net_str=$(ipv4_host_addr_to_net $(IFS="/" ; echo $local))
329 net_str=$(echo "$net_str" | sed -e 's@/@_@')
330 pf="${FAKE_IP_STATE}/addresses/${dev}-${net_str}-primary"
331 sf="${FAKE_IP_STATE}/addresses/${dev}-${net_str}-secondary"
332 # We could lock here... but we should be the only ones playing
333 # around here with these stubs.
334 if [ ! -f "$pf" ] ; then
335 echo "$local $scope" >"$pf"
336 elif grep -Fq "$local" "$pf" ; then
337 echo "RTNETLINK answers: File exists" >&2
339 elif [ -f "$sf" ] && grep -Fq "$local" "$sf" ; then
340 echo "RTNETLINK answers: File exists" >&2
343 echo "$local $scope" >>"$sf"
351 while [ -n "$1" ] ; do
363 not_implemented "addr del ... $1 ..."
366 if [ -z "$dev" ] ; then
367 not_implemented "addr del (without dev)"
369 mkdir -p "${FAKE_IP_STATE}/addresses"
370 net_str=$(ipv4_host_addr_to_net $(IFS="/" ; echo $local))
371 net_str=$(echo "$net_str" | sed -e 's@/@_@')
372 pf="${FAKE_IP_STATE}/addresses/${dev}-${net_str}-primary"
373 sf="${FAKE_IP_STATE}/addresses/${dev}-${net_str}-secondary"
374 # We could lock here... but we should be the only ones playing
375 # around here with these stubs.
376 if [ ! -f "$pf" ] ; then
377 echo "RTNETLINK answers: Cannot assign requested address" >&2
379 elif grep -Fq "$local" "$pf" ; then
380 if $promote_secondaries && [ -s "$sf" ] ; then
381 head -n 1 "$sf" >"$pf"
384 # Remove primaries AND SECONDARIES.
387 elif [ -f "$sf" ] && grep -Fq "$local" "$sf" ; then
388 grep -Fv "$local" "$sf" >"${sf}.new"
391 echo "RTNETLINK answers: Cannot assign requested address" >&2
396 ######################################################################
401 show|list|"") shift ; ip_rule_show "$@" ;;
402 add) shift ; ip_rule_add "$@" ;;
403 del*) shift ; ip_rule_del "$@" ;;
404 *) not_implemented "$1 in \"$orig_args\"" ;;
409 # All non-default rules are in $FAKE_IP_STATE_RULES/rules. As with
410 # the real version, rules can be repeated. Deleting just deletes the
420 # potentially more options
422 printf "%d:\t%s lookup %s \n" $_pre "$_selectors" "$_table"
430 [ -f "${FAKE_IP_STATE}/rules" ] || return
432 while read _pre _table _selectors ; do
433 # Only print those in range
434 [ $_min -le $_pre -a $_pre -le $_max ] || continue
436 ip_rule_show_1 $_pre "$_table" "$_selectors"
437 done <"${FAKE_IP_STATE}/rules"
440 ip_rule_show_1 0 "local" "from all"
442 ip_rule_show_some 1 32765
444 ip_rule_show_1 32766 "main" "from all"
445 ip_rule_show_1 32767 "default" "from all"
447 ip_rule_show_some 32768 2147483648
455 while [ -n "$1" ] ; do
457 from) _from="$2" ; shift 2 ;;
458 pref) _pre="$2" ; shift 2 ;;
459 table) _table="$2" ; shift 2 ;;
460 *) not_implemented "$1 in \"$orig_args\"" ;;
464 [ -n "$_pre" ] || not_implemented "ip rule without \"pref\""
465 ip_check_table "rule"
466 # Relax this if more selectors added later...
467 [ -n "$_from" ] || not_implemented "ip rule without \"from\""
474 _f="${FAKE_IP_STATE}/rules"
478 # Filter order must be consistent with the comparison in ip_rule_del()
479 echo "$_pre $_table${_from:+ from }$_from" >>"$_f"
487 _f="${FAKE_IP_STATE}/rules"
494 while read _p _t _s ; do
496 [ "$_p" = "$_pre" -a "$_t" = "$_table" -a \
497 "$_s" = "${_from:+from }$_from" ] ; then
498 # Found. Skip this one but not future ones.
501 echo "$_p $_t $_s" >>"$_tmp"
504 if cmp -s "$_tmp" "$_f" ; then
505 # No changes, must not have found what we wanted to delete
506 echo "RTNETLINK answers: No such file or directory" >&2
515 ######################################################################
520 show|list) shift ; ip_route_show "$@" ;;
521 flush) shift ; ip_route_flush "$@" ;;
522 add) shift ; ip_route_add "$@" ;;
523 del*) shift ; ip_route_del "$@" ;;
524 *) not_implemented "$1 in \"ip route\"" ;;
530 if [ "$1" = table ] ; then
535 ip_check_table "route"
538 # Routes are in a file per table in the directory
539 # $FAKE_IP_STATE/routes. These routes just use the table ID
540 # that is passed and don't do any lookup. This could be "improved" if
547 # Missing file is just an empty table
548 sort "$FAKE_IP_STATE/routes/${_table}" 2>/dev/null || true
555 rm -f "$FAKE_IP_STATE/routes/${_table}"
566 while [ -n "$1" ] ; do
568 *.*.*.*/*|*.*.*.*) _prefix="$1" ; shift 1 ;;
569 local) _prefix="$2" ; shift 2 ;;
570 dev) _dev="$2" ; shift 2 ;;
571 via) _gw="$2" ; shift 2 ;;
572 table) _table="$2" ; shift 2 ;;
573 metric) _metric="$2" ; shift 2 ;;
574 *) not_implemented "$1 in \"$orig_args\"" ;;
578 ip_check_table "route"
579 [ -n "$_prefix" ] || not_implemented "ip route without inet prefix in \"$orig_args\""
580 # This can't be easily deduced, so print some garbage.
581 [ -n "$_dev" ] || _dev="ethXXX"
583 # Alias or add missing bits
585 0.0.0.0/0) _prefix="default" ;;
587 *) _prefix="${_prefix}/32" ;;
590 _f="$FAKE_IP_STATE/routes/${_table}"
591 mkdir -p "$FAKE_IP_STATE/routes"
594 # Check for duplicate
595 _prefix_regexp=$(echo "^${_prefix}" | sed -e 's@\.@\\.@g')
596 if [ -n "$_metric" ] ; then
597 _prefix_regexp="${_prefix_regexp} .*metric ${_metric} "
599 if grep -q "$_prefix_regexp" "$_f" ; then
600 echo "RTNETLINK answers: File exists" >&2
608 [ -z "$_gw" ] || _out="${_out}via ${_gw} "
609 [ -z "$_dev" ] || _out="${_out}dev ${_dev} "
610 [ -n "$_gw" ] || _out="${_out} scope link "
611 [ -z "$_metric" ] || _out="${_out} metric ${_metric} "
624 while [ -n "$1" ] ; do
626 *.*.*.*/*|*.*.*.*) _prefix="$1" ; shift 1 ;;
627 local) _prefix="$2" ; shift 2 ;;
628 dev) _dev="$2" ; shift 2 ;;
629 via) _gw="$2" ; shift 2 ;;
630 table) _table="$2" ; shift 2 ;;
631 metric) _metric="$2" ; shift 2 ;;
632 *) not_implemented "$1 in \"$orig_args\"" ;;
636 ip_check_table "route"
637 [ -n "$_prefix" ] || not_implemented "ip route without inet prefix in \"$orig_args\""
638 # This can't be easily deduced, so print some garbage.
639 [ -n "$_dev" ] || _dev="ethXXX"
641 # Alias or add missing bits
643 0.0.0.0/0) _prefix="default" ;;
645 *) _prefix="${_prefix}/32" ;;
648 _f="$FAKE_IP_STATE/routes/${_table}"
649 mkdir -p "$FAKE_IP_STATE/routes"
656 [ -z "$_gw" ] || _gw=$(echo "$_gw" | sed -e 's@\.@\\.@g')
657 _prefix=$(echo "$_prefix" | sed -e 's@\.@\\.@g' -e 's@/@\\/@')
659 _re="^${_prefix}\>.*"
660 [ -z "$_gw" ] || _re="${_re}\<via ${_gw}\>.*"
661 [ -z "$_dev" ] || _re="${_re}\<dev ${_dev}\>.*"
662 [ -z "$_metric" ] || _re="${_re}.*\<metric ${_metric}\>.*"
663 sed -i -e "/${_re}/d" "$_f"
667 ######################################################################
672 link) shift ; ip_link "$@" ;;
673 addr*) shift ; ip_addr "$@" ;;
674 rule) shift ; ip_rule "$@" ;;
675 route) shift ; ip_route "$@" ;;
676 *) not_implemented "$1" ;;