flow: Verify that tot_len >= ip_len in miniflow_extract().
[cascardo/ovs.git] / utilities / ovs-ctl.in
1 #! /bin/sh
2 # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2016 Nicira, Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 case $0 in
17     */*) dir0=`echo "$0" | sed 's,/[^/]*$,,'` ;;
18     *) dir0=./ ;;
19 esac
20 . "$dir0/ovs-lib" || exit 1
21
22 for dir in "$sbindir" "$bindir" /sbin /bin /usr/sbin /usr/bin; do
23     case :$PATH: in
24         *:$dir:*) ;;
25         *) PATH=$PATH:$dir ;;
26     esac
27 done
28
29 ## ----- ##
30 ## start ##
31 ## ----- ##
32
33 # Keep track of removed vports so we can reload them if needed
34 removed_vports=""
35
36 insert_mods () {
37     # Try loading openvswitch again.
38     action "Inserting openvswitch module" modprobe openvswitch
39
40     for vport in $removed_vports; do
41         # Don't treat failures to load vports as fatal error
42         action "Inserting $vport module" modprobe $vport || true
43     done
44 }
45
46 insert_mod_if_required () {
47     # If this kernel has no module support, expect we're done.
48     if test ! -e /proc/modules
49     then
50         log_success_msg "Kernel has no loadable module support. Skipping modprobe"
51         return 0
52     fi
53
54     # If openvswitch is already loaded then we're done.
55     test -e /sys/module/openvswitch && return 0
56
57     # Load openvswitch.  If that's successful then we're done.
58     insert_mods && return 0
59
60     # If the bridge module is loaded, then that might be blocking
61     # openvswitch.  Try to unload it, if there are no bridges.
62     test -e /sys/module/bridge || return 1
63     bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
64     if test "$bridges" != "*"; then
65         log_warning_msg "not removing bridge module because bridges exist ($bridges)"
66         return 1
67     fi
68     action "removing bridge module" rmmod bridge || return 1
69
70     # Try loading openvswitch again.
71     insert_mods
72 }
73
74 ovs_vsctl () {
75     ovs-vsctl --no-wait "$@"
76 }
77
78 set_system_ids () {
79     set ovs_vsctl set Open_vSwitch .
80
81     OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'`
82     set "$@" ovs-version="$OVS_VERSION"
83
84     case $SYSTEM_ID in
85         random)
86             id_file=$etcdir/system-id.conf
87             uuid_file=$etcdir/install_uuid.conf
88             if test -e "$id_file"; then
89                 SYSTEM_ID=`cat "$id_file"`
90             elif test -e "$uuid_file"; then
91                 # Migrate from old file name.
92                 . "$uuid_file"
93                 SYSTEM_ID=$INSTALLATION_UUID
94                 echo "$SYSTEM_ID" > "$id_file"
95             elif SYSTEM_ID=`uuidgen`; then
96                 echo "$SYSTEM_ID" > "$id_file"
97             else
98                 log_failure_msg "missing uuidgen, could not generate system ID"
99             fi
100             ;;
101
102         '')
103             log_failure_msg "system ID not configured, please use --system-id"
104             ;;
105
106         *)
107             ;;
108     esac
109     set "$@" external-ids:system-id="\"$SYSTEM_ID\""
110
111     set "$@" external-ids:hostname="\"$(hostname)\""
112
113     if test X"$SYSTEM_TYPE" != X; then
114         set "$@" system-type="\"$SYSTEM_TYPE\""
115     else
116         log_failure_msg "no default system type, please use --system-type"
117     fi
118
119     if test X"$SYSTEM_VERSION" != X; then
120         set "$@" system-version="\"$SYSTEM_VERSION\""
121     else
122         log_failure_msg "no default system version, please use --system-version"
123     fi
124
125     action "Configuring Open vSwitch system IDs" "$@" $extra_ids
126 }
127
128 check_force_cores () {
129     if test X"$FORCE_COREFILES" = Xyes; then
130         ulimit -c 67108864
131     fi
132 }
133
134 del_transient_ports () {
135     for port in `ovs-vsctl --bare -- --columns=name find port other_config:transient=true`; do
136         ovs_vsctl -- del-port "$port"
137     done
138 }
139
140 do_start_ovsdb () {
141     check_force_cores
142
143     if daemon_is_running ovsdb-server; then
144         log_success_msg "ovsdb-server is already running"
145     else
146         # Create initial database or upgrade database schema.
147         upgrade_db $DB_FILE $DB_SCHEMA || return 1
148
149         # Start ovsdb-server.
150         set ovsdb-server "$DB_FILE"
151         for db in $EXTRA_DBS; do
152             case $db in
153                 /*) ;;
154                 *) db=$dbdir/$db ;;
155             esac
156
157             if test ! -f "$db"; then
158                 log_warning_msg "$db (from \$EXTRA_DBS) does not exist."
159             elif ovsdb-tool db-version "$db" >/dev/null; then
160                 set "$@" "$db"
161             else
162                 log_warning_msg "$db (from \$EXTRA_DBS) cannot be read as a database (see error message above)"
163             fi
164         done
165         if test X"$SELF_CONFINEMENT" = Xno; then
166             set "$@" --no-self-confinement
167         fi
168         set "$@" -vconsole:emer -vsyslog:err -vfile:info
169         set "$@" --remote=punix:"$DB_SOCK"
170         set "$@" --private-key=db:Open_vSwitch,SSL,private_key
171         set "$@" --certificate=db:Open_vSwitch,SSL,certificate
172         set "$@" --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert
173         start_daemon "$OVSDB_SERVER_PRIORITY" "$OVSDB_SERVER_WRAPPER" "$@" \
174             || return 1
175
176         # Initialize database settings.
177         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
178             || return 1
179         set_system_ids || return 1
180         if test X"$DELETE_BRIDGES" = Xyes; then
181             for bridge in `ovs_vsctl list-br`; do
182                 ovs_vsctl del-br $bridge
183             done
184         fi
185         if test X"$DELETE_TRANSIENT_PORTS" = Xyes; then
186             del_transient_ports
187         fi
188     fi
189 }
190
191 start_ovsdb() {
192     if test X"$OVSDB_SERVER" = Xyes; then
193         do_start_ovsdb
194     fi
195 }
196
197 add_managers () {
198     # Now that ovs-vswitchd has started and completed its initial
199     # configuration, tell ovsdb-server to conenct to the remote managers.  We
200     # used to do this at ovsdb-server startup time, but waiting for
201     # ovs-vswitchd to finish configuring means that remote managers see less
202     # churn in the database at startup or restart.  (For example, managers
203     # won't briefly see empty datapath-id or ofport columns for records that
204     # exist at startup.)
205     if test X"$OVSDB_SERVER" = Xyes || test X"$OVS_VSWITCHD" = Xyes; then
206         if daemon_is_running ovsdb-server \
207                 && daemon_is_running ovs-vswitchd; then
208             action "Enabling remote OVSDB managers" \
209                    ovs-appctl -t ovsdb-server ovsdb-server/add-remote \
210                    db:Open_vSwitch,Open_vSwitch,manager_options
211         fi
212     fi
213 }
214
215 do_start_forwarding () {
216     check_force_cores
217
218     insert_mod_if_required || return 1
219
220     if daemon_is_running ovs-vswitchd; then
221         log_success_msg "ovs-vswitchd is already running"
222     else
223         # Increase the limit on the number of open file descriptors.
224         # On Linux, ovs-vswitchd needs about three file descriptors
225         # per bridge and "n-handler-threads" file descriptors per bridge
226         # port, so this allows a very large number of bridges and ports.
227         MAXFD=65535
228         if [ $(ulimit -n) -lt $MAXFD ]; then
229             ulimit -n $MAXFD
230         fi
231
232         # Start ovs-vswitchd.
233         set ovs-vswitchd unix:"$DB_SOCK"
234         set "$@" -vconsole:emer -vsyslog:err -vfile:info
235         if test X"$MLOCKALL" != Xno; then
236             set "$@" --mlockall
237         fi
238         if test X"$SELF_CONFINEMENT" = Xno; then
239             set "$@" --no-self-confinement
240         fi
241         start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
242     fi
243 }
244
245 start_forwarding () {
246     if test X"$OVS_VSWITCHD" = Xyes; then
247         do_start_forwarding
248     fi
249 }
250
251 ## ---- ##
252 ## stop ##
253 ## ---- ##
254
255 stop_ovsdb () {
256     if test X"$OVSDB_SERVER" = Xyes; then
257         stop_daemon ovsdb-server
258     fi
259 }
260
261 stop_forwarding () {
262     if test X"$OVS_VSWITCHD" = Xyes; then
263         stop_daemon ovs-vswitchd
264     fi
265 }
266
267 ## ----------------- ##
268 ## force-reload-kmod ##
269 ## ----------------- ##
270
271 internal_interfaces () {
272     # Outputs a list of internal interfaces:
273     #
274     #   - There is an internal interface for every bridge, whether it
275     #     has an Interface record or not and whether the Interface
276     #     record's 'type' is properly set or not.
277     #
278     #   - There is an internal interface for each Interface record whose
279     #     'type' is 'internal'.
280     #
281     # But ignore interfaces that don't really exist.
282     for d in `(ovs_vsctl --bare \
283                 -- --columns=name find Interface type=internal \
284                     -- list-br) | sort -u`
285     do
286         if test -e "/sys/class/net/$d"; then
287                 printf "%s " "$d"
288             fi
289     done
290 }
291
292 ovs_save () {
293     bridges=`ovs_vsctl -- --real list-br`
294     if [ -n "${bridges}" ] && \
295         "$datadir/scripts/ovs-save" "$1" ${bridges} > "$2"; then
296         chmod +x "$2"
297         return 0
298     fi
299     [ -z "${bridges}" ] && return 0
300 }
301
302 save_flows_if_required () {
303     if test X"$DELETE_BRIDGES" != Xyes; then
304         action "Saving flows" ovs_save save-flows "${script_flows}"
305     fi
306 }
307
308 save_interfaces () {
309     "$datadir/scripts/ovs-save" save-interfaces ${ifaces} \
310         > "${script_interfaces}"
311 }
312
313 flow_restore_wait () {
314     if test X"$OVS_VSWITCHD" = Xyes; then
315         ovs_vsctl set open_vswitch . other_config:flow-restore-wait="true"
316     fi
317 }
318
319 flow_restore_complete () {
320     if test X"$OVS_VSWITCHD" = Xyes; then
321         ovs_vsctl --if-exists remove open_vswitch . other_config \
322                   flow-restore-wait="true"
323     fi
324 }
325
326 restore_flows () {
327     [ -x "${script_flows}" ] && \
328         action "Restoring saved flows" "${script_flows}"
329 }
330
331 restore_interfaces () {
332     [ ! -x "${script_interfaces}" ] && return 0
333     action "Restoring interface configuration" "${script_interfaces}"
334     rc=$?
335     if test $rc = 0; then
336         level=debug
337     else
338         level=err
339     fi
340     log="logger -p daemon.$level -t ovs-save"
341     $log "interface restore script exited with status $rc:"
342     $log -f "$script_interfaces"
343 }
344
345 init_restore_scripts () {
346     script_interfaces=`mktemp`
347     script_flows=`mktemp`
348     trap 'rm -f "${script_interfaces}" "${script_flows}"' 0
349 }
350
351 force_reload_kmod () {
352
353     if test X"$OVS_VSWITCHD" != Xyes; then
354         log_failure_msg "Reloading of kmod without ovs-vswitchd is an error"
355         exit 1
356     fi
357
358     ifaces=`internal_interfaces`
359     action "Detected internal interfaces: $ifaces" true
360
361     init_restore_scripts
362     save_flows_if_required
363
364     # Restart the database first, since a large database may take a
365     # while to load, and we want to minimize forwarding disruption.
366     stop_ovsdb
367     start_ovsdb
368
369     stop_forwarding
370
371     if action "Saving interface configuration" save_interfaces; then
372         :
373     else
374         log_warning_msg "Failed to save configuration, not replacing kernel module"
375         start_forwarding
376         add_managers
377         exit 1
378     fi
379     chmod +x "$script_interfaces"
380
381     for dp in `ovs-dpctl dump-dps`; do
382         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
383     done
384
385     for vport in `awk '/^vport_/ { print $1 }' /proc/modules`; do
386         action "Removing $vport module" rmmod $vport
387         if ! grep -q $vport /proc/modules; then
388             removed_vports="$removed_vports $vport"
389         fi
390     done
391
392     if test -e /sys/module/openvswitch; then
393         action "Removing openvswitch module" rmmod openvswitch
394     fi
395
396     # Start vswitchd by asking it to wait till flow restore is finished.
397     flow_restore_wait
398     start_forwarding
399
400     # Restore saved flows and inform vswitchd that we are done.
401     restore_flows
402     flow_restore_complete
403     add_managers
404
405     restore_interfaces
406
407     "$datadir/scripts/ovs-check-dead-ifs"
408 }
409
410 ## ------- ##
411 ## restart ##
412 ## ------- ##
413
414 restart () {
415     if daemon_is_running ovsdb-server && daemon_is_running ovs-vswitchd; then
416         init_restore_scripts
417         if test X"$OVS_VSWITCHD" = Xyes; then
418             save_flows_if_required
419         fi
420     fi
421
422     # Restart the database first, since a large database may take a
423     # while to load, and we want to minimize forwarding disruption.
424     stop_ovsdb
425     start_ovsdb
426
427     stop_forwarding
428
429     # Start vswitchd by asking it to wait till flow restore is finished.
430     flow_restore_wait
431     start_forwarding
432
433     # Restore saved flows and inform vswitchd that we are done.
434     restore_flows
435     flow_restore_complete
436     add_managers
437
438     # Restore the interfaces if required. Return true even if restore fails.
439     restore_interfaces || true
440 }
441
442 ## --------------- ##
443 ## enable-protocol ##
444 ## --------------- ##
445
446 enable_protocol () {
447     # Translate the protocol name to a number, because "iptables -n -L" prints
448     # some protocols by name (despite the -n) and therefore we need to look for
449     # both forms.
450     #
451     # (iptables -S output is more uniform but old iptables doesn't have it.)
452     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
453     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
454         log_failure_msg "unknown protocol $PROTOCOL"
455         return 1
456     fi
457
458     name=$PROTOCOL
459     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
460     insert="iptables -I INPUT -p $PROTOCOL"
461     if test X"$DPORT" != X; then
462         name="$name to port $DPORT"
463         match="$match && /dpt:$DPORT/"
464         insert="$insert --dport $DPORT"
465     fi
466     if test X"$SPORT" != X; then
467         name="$name from port $SPORT"
468         match="$match && /spt:$SPORT/"
469         insert="$insert --sport $SPORT"
470     fi
471     insert="$insert -j ACCEPT"
472
473     if (iptables -n -L INPUT) >/dev/null 2>&1; then
474         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
475         then
476             # There's already a rule for this protocol.  Don't override it.
477             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
478         else
479             action "Enabling $name with iptables" $insert
480         fi
481     elif (iptables --version) >/dev/null 2>&1; then
482         action "cannot list iptables rules, not adding a rule for $name"
483     else
484         action "iptables binary not installed, not adding a rule for $name"
485     fi
486 }
487
488 ## ---- ##
489 ## main ##
490 ## ---- ##
491
492 set_defaults () {
493     SYSTEM_ID=
494
495     DELETE_BRIDGES=no
496     DELETE_TRANSIENT_PORTS=no
497
498     DAEMON_CWD=/
499     FORCE_COREFILES=yes
500     MLOCKALL=yes
501     SELF_CONFINEMENT=yes
502     OVSDB_SERVER=yes
503     OVS_VSWITCHD=yes
504     OVSDB_SERVER_PRIORITY=-10
505     OVS_VSWITCHD_PRIORITY=-10
506     OVSDB_SERVER_WRAPPER=
507     OVS_VSWITCHD_WRAPPER=
508
509     DB_FILE=$dbdir/conf.db
510     DB_SOCK=$rundir/db.sock
511     DB_SCHEMA=$datadir/vswitch.ovsschema
512     EXTRA_DBS=
513
514     PROTOCOL=gre
515     DPORT=
516     SPORT=
517
518     type_file=$etcdir/system-type.conf
519     version_file=$etcdir/system-version.conf
520
521     if test -e "$type_file" ; then
522         SYSTEM_TYPE=`cat $type_file`
523         SYSTEM_VERSION=`cat $version_file`
524     elif (lsb_release --id) >/dev/null 2>&1; then
525         SYSTEM_TYPE=`lsb_release --id -s`
526         system_release=`lsb_release --release -s`
527         system_codename=`lsb_release --codename -s`
528         SYSTEM_VERSION="${system_release}-${system_codename}"
529     else
530         SYSTEM_TYPE=unknown
531         SYSTEM_VERSION=unknown
532     fi
533 }
534
535 usage () {
536     set_defaults
537     cat <<EOF
538 $0: controls Open vSwitch daemons
539 usage: $0 [OPTIONS] COMMAND
540
541 This program is intended to be invoked internally by Open vSwitch startup
542 scripts.  System administrators should not normally invoke it directly.
543
544 Commands:
545   start              start Open vSwitch daemons
546   stop               stop Open vSwitch daemons
547   restart            stop and start Open vSwitch daemons
548   status             check whether Open vSwitch daemons are running
549   version            print versions of Open vSwitch daemons
550   load-kmod          insert modules if not already present
551   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
552                      module, reload kernel module, start OVS, restore state
553   enable-protocol    enable protocol specified in options with iptables
554   help               display this help message
555
556 One of the following options is required for "start", "restart" and "force-reload-kmod":
557   --system-id=UUID   set specific ID to uniquely identify this system
558   --system-id=random  use a random but persistent UUID to identify this system
559
560 Other important options for "start", "restart" and "force-reload-kmod":
561   --system-type=TYPE  set system type (e.g. "XenServer")
562   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
563   --external-id="key=value"
564                      add given key-value pair to Open_vSwitch external-ids
565   --delete-bridges   delete all bridges just before starting ovs-vswitchd
566
567 Less important options for "start", "restart" and "force-reload-kmod":
568   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
569   --no-force-corefiles           do not force on core dumps for OVS daemons
570   --no-mlockall                  do not lock all of ovs-vswitchd into memory
571   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
572   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
573
574 Debugging options for "start", "restart" and "force-reload-kmod":
575   --ovsdb-server-wrapper=WRAPPER
576   --ovs-vswitchd-wrapper=WRAPPER
577      run specified daemon under WRAPPER (either 'valgrind' or 'strace')
578
579 File location options:
580   --db-file=FILE     database file name (default: $DB_FILE)
581   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
582   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
583
584 Options for "enable-protocol":
585   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
586   --sport=PORT       source port to match (for tcp or udp protocol)
587   --dport=PORT       ddestination port to match (for tcp or udp protocol)
588
589 Other options:
590   -h, --help                  display this help message
591   -V, --version               display version information
592
593 Default directories with "configure" option and environment variable override:
594   logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
595   pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
596   conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
597   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
598   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
599   user binaries: @bindir@ (--bindir, OVS_BINDIR)
600   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
601
602 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
603 EOF
604
605     exit 0
606 }
607
608 set_option () {
609     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
610     eval set=\${$var+yes}
611     eval old_value=\$$var
612     if test X$set = X || \
613         (test $type = bool && \
614         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
615         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
616         return
617     fi
618     eval $var=\$value
619 }
620
621 daemons () {
622     echo ovsdb-server ovs-vswitchd
623 }
624
625 set_defaults
626 extra_ids=
627 command=
628 for arg
629 do
630     case $arg in
631         -h | --help)
632             usage
633             ;;
634         -V | --version)
635             echo "$0 (Open vSwitch) $VERSION"
636             exit 0
637             ;;
638         --external-id=*)
639             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
640             case $value in
641                 *=*)
642                     extra_ids="$extra_ids external-ids:$value"
643                     ;;
644                 *)
645                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
646                     exit 1
647                     ;;
648             esac
649             ;;
650         --[a-z]*=*)
651             option=`expr X"$arg" : 'X--\([^=]*\)'`
652             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
653             type=string
654             set_option
655             ;;
656         --no-[a-z]*)
657             option=`expr X"$arg" : 'X--no-\(.*\)'`
658             value=no
659             type=bool
660             set_option
661             ;;
662         --[a-z]*)
663             option=`expr X"$arg" : 'X--\(.*\)'`
664             value=yes
665             type=bool
666             set_option
667             ;;
668         -*)
669             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
670             exit 1
671             ;;
672         *)
673             if test X"$command" = X; then
674                 command=$arg
675             else
676                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
677                 exit 1
678             fi
679             ;;
680     esac
681 done
682 case $command in
683     start)
684         start_ovsdb || exit 1
685         start_forwarding
686         add_managers
687         ;;
688     stop)
689         stop_forwarding
690         stop_ovsdb
691         ;;
692     restart)
693         restart
694         ;;
695     status)
696         rc=0
697         for daemon in `daemons`; do
698             daemon_status $daemon || rc=$?
699         done
700         exit $rc
701         ;;
702     version)
703         for daemon in `daemons`; do
704             $daemon --version
705         done
706         ;;
707     force-reload-kmod)
708             force_reload_kmod
709         ;;
710     load-kmod)
711         insert_mod_if_required
712         ;;
713     enable-protocol)
714         enable_protocol
715         ;;
716     help)
717         usage
718         ;;
719     '')
720         echo >&2 "$0: missing command name (use --help for help)"
721         exit 1
722         ;;
723     *)
724         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
725         exit 1
726         ;;
727 esac