tests/eventscripts: Add tests for monitoring of missing interfaces
[Samba.git] / ctdb / tests / eventscripts / stubs / ip
blob053da750b9cb7a21015c39cf94e4bdce17ab1022
1 #!/bin/sh
3 not_implemented ()
5 echo "ip stub command: \"$1\" not implemented"
6 exit 127
9 ######################################################################
11 ip_link ()
13 case "$1" in
14 set)
15 shift
16 # iface="$1"
17 case "$2" in
18 up) ip_link_set_up "$1" ;;
19 down) ip_link_down_up "$1" ;;
20 *) not_implemented "\"$2\" in \"$orig_args\"" ;;
21 esac
23 show) shift ; ip_link_show "$@" ;;
24 del*) shift ; ip_link_delete "$@" ;;
25 *) not_implemented "$*" ;;
26 esac
29 ip_link_delete ()
31 mkdir -p "${FAKE_IP_STATE}/interfaces-deleted"
32 touch "${FAKE_IP_STATE}/interfaces-deleted/$1"
35 ip_link_set_up ()
37 rm -f "${FAKE_IP_STATE}/interfaces-down/$1"
38 rm -f "${FAKE_IP_STATE}/interfaces-deleted/$1"
41 ip_link_set_down ()
43 rm -f "${FAKE_IP_STATE}/interfaces-deleted/$1"
44 mkdir -p "${FAKE_IP_STATE}/interfaces-down"
45 touch "${FAKE_IP_STATE}/interfaces-down/$1"
48 ip_link_show ()
50 dev="$1"
51 if [ "$dev" = "dev" -a -n "$2" ] ; then
52 dev="$2"
55 if [ -e "${FAKE_IP_STATE}/interfaces-deleted/$dev" ] ; then
56 echo "Device \"${dev}\" does not exist." >&2
57 exit 255
60 mac=$(echo $dev | md5sum | sed -r -e 's@(..)(..)(..)(..)(..)(..).*@\1:\2:\3:\4:\5:\6@')
61 _state="UP"
62 _flags=",UP,LOWER_UP"
63 if [ -e "${FAKE_IP_STATE}/interfaces-down/$dev" ] ; then
64 _state="DOWN"
65 _flags=""
67 cat <<EOF
68 ${n}: ${dev}: <BROADCAST,MULTICAST${_flags}> mtu 1500 qdisc pfifo_fast state ${_state} qlen 1000
69 link/ether ${mac} brd ff:ff:ff:ff:ff:ff
70 EOF
73 # This is incomplete because it doesn't actually look up table ids in
74 # /etc/iproute2/rt_tables. The rules/routes are actually associated
75 # with the name instead of the number. However, we include a variable
76 # to fake a bad table id.
77 [ -n "$IP_ROUTE_BAD_TABLE_ID" ] || IP_ROUTE_BAD_TABLE_ID=false
79 ip_check_table ()
81 _cmd="$1"
83 [ -n "$_table" ] || not_implemented "ip rule/route without \"table\""
85 # Only allow tables names from 13.per_ip_routing. This is a cheap
86 # way of avoiding implementing the default/main/local tables.
87 case "$_table" in
88 ctdb.*)
89 if $IP_ROUTE_BAD_TABLE_ID ; then
90 # Ouch. Simulate inconsistent errors from ip. :-(
91 case "$_cmd" in
92 route)
93 echo "Error: argument "${_table}" is wrong: table id value is invalid" >&2
97 echo "Error: argument "${_table}" is wrong: invalid table ID" >&2
98 esac
99 exit 255
102 *) not_implemented "table=${_table} ${orig_args}" ;;
103 esac
106 ######################################################################
108 ip_addr ()
110 case "$1" in
111 show|list|"") shift ; ip_addr_show "$@" ;;
112 add*) shift ; ip_addr_add "$@" ;;
113 del*) shift ; ip_addr_del "$@" ;;
114 *) not_implemented "\"$1\" in \"$orig_args\"" ;;
115 esac
118 ip_addr_show ()
120 dev=""
121 primary=true
122 secondary=true
123 _to=""
124 while [ -n "$1" ] ; do
125 case "$1" in
126 dev)
127 dev="$2" ; shift 2
129 # Do stupid things and stupid things will happen!
130 primary)
131 primary=true ; secondary=false ; shift
133 secondary)
134 secondary=true ; primary=false ; shift
137 _to="$2" ; shift 2
140 # Assume an interface name
141 dev="$1" ; shift 1
142 esac
143 done
144 devices="$dev"
145 if [ -z "$devices" ] ; then
146 # No device specified? Get all the primaries...
147 devices=$(ls "${FAKE_IP_STATE}/addresses/"*-primary 2>/dev/null | \
148 sed -e 's@.*/@@' -e 's@-primary$@@')
150 calc_brd ()
152 case "${local#*/}" in
154 brd="${local%.*}.255"
157 not_implemented "list ... fake bits other than 24: ${local#*/}"
158 esac
160 show_iface()
162 pf="${FAKE_IP_STATE}/addresses/${dev}-primary"
163 sf="${FAKE_IP_STATE}/addresses/${dev}-secondary"
164 ip_link_show "$dev"
165 if $primary && [ -r "$pf" ] ; then
166 read local <"$pf"
167 if [ -z "$_to" -o "${_to%/*}" = "${local%/*}" ] ; then
168 calc_brd
169 cat <<EOF
170 inet ${local} brd ${brd} scope global ${dev}
174 if $secondary && [ -r "$sf" ] ; then
175 while read local ; do
176 if [ -z "$_to" -o "${_to%/*}" = "${local%/*}" ] ; then
177 calc_brd
178 cat <<EOF
179 inet ${local} brd ${brd} scope global secondary ${dev}
182 done <"$sf"
184 if [ -z "$_to" ] ; then
185 cat <<EOF
186 valid_lft forever preferred_lft forever
191 for dev in $devices ; do
192 if [ -z "$_to" ] || \
193 grep -F "${_to%/*}/" "${FAKE_IP_STATE}/addresses/${dev}-"* >/dev/null ; then
194 show_iface
196 n=$(($n + 1))
197 done
200 ip_addr_add ()
202 local=""
203 dev=""
204 brd=""
205 while [ -n "$1" ] ; do
206 case "$1" in
207 *.*.*.*/*)
208 local="$1" ; shift
210 local)
211 local="$2" ; shift 2
213 broadcast|brd)
214 # For now assume this is always '+'.
215 if [ "$2" != "+" ] ; then
216 not_implemented "addr add ... brd $2 ..."
218 shift 2
220 dev)
221 dev="$2" ; shift 2
224 not_implemented "$@"
225 esac
226 done
227 if [ -z "$dev" ] ; then
228 not_implemented "addr add (without dev)"
230 mkdir -p "${FAKE_IP_STATE}/addresses"
231 pf="${FAKE_IP_STATE}/addresses/${dev}-primary"
232 sf="${FAKE_IP_STATE}/addresses/${dev}-secondary"
233 # We could lock here... but we should be the only ones playing
234 # around here with these stubs.
235 if [ ! -f "$pf" ] ; then
236 echo "$local" >"$pf"
237 elif grep -Fq "$local" "$pf" ; then
238 echo "RTNETLINK answers: File exists" >&2
239 exit 254
240 elif [ -f "$sf" ] && grep -Fq "$local" "$sf" ; then
241 echo "RTNETLINK answers: File exists" >&2
242 exit 254
243 else
244 echo "$local" >>"$sf"
248 ip_addr_del ()
250 local=""
251 dev=""
252 while [ -n "$1" ] ; do
253 case "$1" in
254 *.*.*.*/*)
255 local="$1" ; shift
257 local)
258 local="$2" ; shift 2
260 dev)
261 dev="$2" ; shift 2
264 not_implemented "addr del ... $1 ..."
265 esac
266 done
267 if [ -z "$dev" ] ; then
268 not_implemented "addr del (without dev)"
270 mkdir -p "${FAKE_IP_STATE}/addresses"
271 pf="${FAKE_IP_STATE}/addresses/${dev}-primary"
272 sf="${FAKE_IP_STATE}/addresses/${dev}-secondary"
273 # We could lock here... but we should be the only ones playing
274 # around here with these stubs.
275 if [ ! -f "$pf" ] ; then
276 echo "RTNETLINK answers: Cannot assign requested address" >&2
277 exit 254
278 elif grep -Fq "$local" "$pf" ; then
279 # Remove primaries AND SECONDARIES.
280 rm -f "$pf" "$sf"
281 elif [ -f "$sf" ] && grep -Fq "$local" "$sf" ; then
282 grep -Fv "$local" "$sf" >"${sf}.new"
283 mv "${sf}.new" "$sf"
284 else
285 echo "RTNETLINK answers: Cannot assign requested address" >&2
286 exit 254
290 ######################################################################
292 ip_rule ()
294 case "$1" in
295 show|list|"") shift ; ip_rule_show "$@" ;;
296 add) shift ; ip_rule_add "$@" ;;
297 del*) shift ; ip_rule_del "$@" ;;
298 *) not_implemented "$1 in \"$orig_args\"" ;;
299 esac
303 # All non-default rules are in $FAKE_IP_STATE_RULES/rules. As with
304 # the real version, rules can be repeated. Deleting just deletes the
305 # 1st match.
307 ip_rule_show ()
309 ip_rule_show_1 ()
311 _pre="$1"
312 _table="$2"
313 _selectors="$3"
314 # potentially more options
316 printf "%d:\t%s lookup %s \n" $_pre "$_selectors" "$_table"
319 ip_rule_show_some ()
321 _min="$1"
322 _max="$2"
324 [ -f "${FAKE_IP_STATE}/rules" ] || return
326 while read _pre _table _selectors ; do
327 # Only print those in range
328 [ $_min -le $_pre -a $_pre -le $_max ] || continue
330 ip_rule_show_1 $_pre "$_table" "$_selectors"
331 done <"${FAKE_IP_STATE}/rules"
334 ip_rule_show_1 0 "local" "from all"
336 ip_rule_show_some 1 32765
338 ip_rule_show_1 32766 "main" "from all"
339 ip_rule_show_1 32767 "default" "from all"
341 ip_rule_show_some 32768 2147483648
344 ip_rule_common ()
346 _from=""
347 _pre=""
348 _table=""
349 while [ -n "$1" ] ; do
350 case "$1" in
351 from) _from="$2" ; shift 2 ;;
352 pref) _pre="$2" ; shift 2 ;;
353 table) _table="$2" ; shift 2 ;;
354 *) not_implemented "$1 in \"$orig_args\"" ;;
355 esac
356 done
358 [ -n "$_pre" ] || not_implemented "ip rule without \"pref\""
359 ip_check_table "rule"
360 # Relax this if more selectors added later...
361 [ -n "$_from" ] || not_implemented "ip rule without \"from\""
364 ip_rule_add ()
366 ip_rule_common "$@"
368 _f="${FAKE_IP_STATE}/rules"
369 touch "$_f"
371 flock 0
372 # Filter order must be consistent with the comparison in ip_rule_del()
373 echo "$_pre $_table${_from:+ from }$_from" >>"$_f"
374 ) <"$_f"
377 ip_rule_del ()
379 ip_rule_common "$@"
381 _f="${FAKE_IP_STATE}/rules"
382 touch "$_f"
384 flock 0
385 _tmp="$(mktemp)"
386 _found=false
387 while read _p _t _s ; do
388 if ! $_found && \
389 [ "$_p" = "$_pre" -a "$_t" = "$_table" -a \
390 "$_s" = "${_from:+from }$_from" ] ; then
391 # Found. Skip this one but not future ones.
392 _found=true
393 else
394 echo "$_p $_t $_s" >>"$_tmp"
396 done
397 if cmp -s "$_tmp" "$_f" ; then
398 # No changes, must not have found what we wanted to delete
399 echo "RTNETLINK answers: No such file or directory" >&2
400 rm -f "$_tmp"
401 exit 2
402 else
403 mv "$_tmp" "$_f"
405 ) <"$_f" || exit $?
408 ######################################################################
410 ip_route ()
412 case "$1" in
413 show|list) shift ; ip_route_show "$@" ;;
414 flush) shift ; ip_route_flush "$@" ;;
415 add) shift ; ip_route_add "$@" ;;
416 *) not_implemented "$1 in \"ip route\"" ;;
417 esac
420 ip_route_common ()
422 [ "$1" = table ] || not_implemented "$1 in \"$orig_args\""
423 _table="$2"
425 ip_check_table "route"
428 # Routes are in a file per table in the directory
429 # $FAKE_IP_STATE/routes. These routes just use the table ID
430 # that is passed and don't do any lookup. This could be "improved" if
431 # necessary.
433 ip_route_show ()
435 ip_route_common "$@"
437 # Missing file is just an empty table
438 cat "$FAKE_IP_STATE/routes/${_table}" 2>/dev/null || true
441 ip_route_flush ()
443 ip_route_common "$@"
445 rm -f "$FAKE_IP_STATE/routes/${_table}"
448 ip_route_add ()
450 _prefix=""
451 _dev=""
452 _gw=""
453 _table=""
455 while [ -n "$1" ] ; do
456 case "$1" in
457 *.*.*.*/*|*.*.*.*) _prefix="$1" ; shift 1 ;;
458 local) _prefix="$2" ; shift 2 ;;
459 dev) _dev="$2" ; shift 2 ;;
460 via) _gw="$2" ; shift 2 ;;
461 table) _table="$2" ; shift 2 ;;
462 *) not_implemented "$1 in \"$orig_args\"" ;;
463 esac
464 done
466 ip_check_table "route"
467 [ -n "$_prefix" ] || not_implemented "ip route without inet prefix in \"$orig_args\""
468 [ -n "$_dev" ] || not_implemented "ip route without \"dev\" in \"$orig_args\""
470 # Alias or add missing bits
471 case "$_prefix" in
472 0.0.0.0/0) _prefix="default" ;;
473 */*) : ;;
474 *) _prefix="${_prefix}/32" ;;
475 esac
477 _f="$FAKE_IP_STATE/routes/${_table}"
478 mkdir -p "$FAKE_IP_STATE/routes"
479 touch "$_f"
482 flock 0
484 if [ -n "$_gw" ] ; then
485 echo "${_prefix} via ${_gw} dev ${_dev} "
486 else
487 echo "${_prefix} dev ${_dev} scope link "
488 fi >>"$_f"
489 ) <"$_f"
493 ######################################################################
495 orig_args="$*"
497 case "$1" in
498 link) shift ; ip_link "$@" ;;
499 addr*) shift ; ip_addr "$@" ;;
500 rule) shift ; ip_rule "$@" ;;
501 route) shift ; ip_route "$@" ;;
502 *) not_implemented "$1" ;;
503 esac
505 exit 0