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