#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
SVCMETHOD= svc-legacy-routing svc-forwarding
MANIFEST= legacy-routing.xml forwarding.xml
PROG= routeadm
ROOTFS_PROG= $(PROG)
include ../../../Makefile.cmd
#
# We cannot use the usual manifest rules here since we deliver
# manifests to two different locations, /lib/svc/manifest/network/forwarding.xml
# and /lib/svc/manifest/network/routing/legacy-routing.xml
#
ROOTSVCMANIFESTDIR= $(ROOTSVCNETWORK) $(ROOTSVCNETWORKROUTING)
ROOTSVCMANIFESTS= $(ROOTSVCNETWORKROUTING)/legacy-routing.xml \
$(ROOTSVCNETWORK)/forwarding.xml
include ../../Makefile.cmd-inet
$(ROOTSVCMANIFESTS) : FILEMODE= 444
ROOTUSRSBINLINKS= $(PROG:%=$(ROOTUSRSBIN)/%)
CPPFLAGS += -I../../../../common/svc -I$(CMDINETCOMMONDIR)
CERRWARN += -Wno-parentheses
CERRWARN += $(CNOWARN_UNINIT)
$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG
LDLIBS += -lscf -luutil -lsocket
ROOTSBINPROG= $(ROOTFS_PROG:%=$(ROOTSBIN)/%)
.KEEP_STATE:
all: $(PROG)
install: all $(ROOTSBINPROG) $(ROOTUSRSBINLINKS) $(ROOTSVCMANIFESTS) \
$(ROOTSVCMETHOD)
$(ROOTUSRSBINLINKS):
-$(RM) $@; $(SYMLINK) ../../sbin/$(@F) $@
check: $(CHKMANIFEST)
clean:
lint: lint_PROG
$(ROOTSVCMANIFESTS): $(ROOTSVCMANIFESTDIR)
$(ROOTSVCMANIFESTDIR):
$(INS.dir)
$(ROOTSVCNETWORK)/%: %
$(INS.file)
$(ROOTSVCNETWORKROUTING)/%: %
$(INS.file)
include ../../../Makefile.targ
IPv4 forwarding service
IPv4 forwarding service, controlled by routeadm.
IPv6 forwarding service
IPv6 forwarding service, controlled by routeadm.
Legacy routing service
Legacy routing services, controlled by routeadm.
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
* This program moves routing management under SMF. We do this by giving
* routeadm options that allow interaction with SMF services. These include:
* - setting the routing services routeadm will enable
* # routeadm -s routing-svcs="fmri [fmri...]"
* where each fmri is an SMF routing service.
* - changing properties of routing services
* # routeadm -m fmri key=value [key=value...]
* - listing routing daemon properties
* # routeadm -l fmri
* where all properties in the "routing" property group are listed.
*
* By providing legacy routing services (legacy-routing:ipv4 and ipv6), we
* can also support running of routing daemons with no SMF service under SMF.
* Specifying a routing daemon with no SMF counterpart results in the
* daemon, it`s arguments and stop command being set in the appropriate instance
* to be picked up by start/stop methods.
*
* Internally, routeadm keeps track of routing services by setting the
* "current-routing-svc" property to "true" in the services it manages.
* So for example, running
* # routeadm -s routing-svcs="route:default ripng:default"
* sets this variable in each instance specified. If the user specifies a
* non-SMF routing daemon via
* # routeadm -s ipv4-routing-daemon=/usr/sbin/mydaemon
* the variable will be set for the legacy-routing:ipv4 instance.
*
* In order to ensure that the SMF versions of routing daemons are used
* where possible, routeadm will check the daemons specified in
* ipv4-routing-daemon/ipv6-routing-daemon to determine if there is an
* SMF counterpart. If so, rather than running the legacy service
* we move configuration, specifically the associated daemon arguments
* to the SMF counterpart. From there, when the daemon is enabled, it
* will pick up the daemon arguments setting, transfer the argument string
* to the appropriate properties and run the service.
*
* To support the semantics of routeadm -e (enable at next boot) through SMF,
* we make use of temporary state changes, which last only until reboot.
* For example, if a service is disabled, and it is to be enabled via
* routeadm -e, we simply change the disable to a temporary disable,
* and set the persistent enabled value to true. This ensures the daemon
* will run at next boot, but not now. The reverse is true for disabling
* enabled instances (and if the daemon is enabled when we issue the enable,
* we do nothing since it is already in the desired state).
*
* Since the code is quite involved, we provide a guide to the more complex
* actions taken in response to user commands.
*
* routeadm -e[d] ipv4[6]-routing[forwarding]
*
* In this case, the goal is to prepare the configured routing daemons
* (specified through routeadm -s routing-svcs="...") or forwarding
* services to switch on (-e) or of (-d) at next boot.
*
* Since this operation must be applied to multiple services in the
* routing daemon case (as opposed to the single ipv4[6]-forwarding
* service), we make use of the scf_walk_fmri() function, which
* applies a callback function to all matching functions. In the case
* of the routing daemons, we pass in a NULL signifying that all
* instances should be walked (we then weed out the relevant routing
* services through presence of the routeadm/protocol property). In
* the case of enable, a routing service is enabled IFF it has the
* previously-mentioned property - with an appropriate value (i.e. ipv4
* for "routeadm -e ipv4-routing") - and it has routeadm/curr-routing-svc
* property set to true (this is set by other operations such as
* routeadm -s routing-svcs="..."). Then, smf_enable_instance() or
* smf_disable_instance() is called, setting the temporary state to
* the current state of the service. This then allows setting of
* general/enabled value to next-boot value. In the case of disabling
* ipv4[6]-routing, all valid ipv4[6] routing daemons are prepared
* for next-boot disable, not just those specified via routing-svcs (this
* means that if the user enables routing daemons with "svcadm enable",
* disabling global routing does really switch off all routing daemons).
*
* This is implemented through the ra_get_set_opt_common_cb() function,
* called by the ra_set_persistent_opt_cb() function. The same
* function can be used for both routing and forwarding options, in the
* latter case we simply provide the specific FMRI of the forwarding
* service in question (ipv4-forwarding or ipv6-forwarding), and dispense
* with the eligibility tests we need to weed out the routing services
* from the rest.
*
* Before we initiate the "enable" however, we must check routing daemons
* specified via the legacy variables (ipv4-routing-daemon etc).
* If they map to SMF routing services, we wish to transfer their
* configuration to the corresponding services and use them instead of
* the legacy services. To do this, we need to match the daemon program
* against the routeadm/daemon property of each routing daemon (we use
* scf_walk_fmri() and the routeadm/protocol property again to identify
* daemons). If a match is found, the daemon arguments are transferred
* to the appropriate service`s daemon-args property, to be picked up
* by it`s start method and converted into appropriate property values.
* This is accomplished by ra_check_legacy_daemons(), and the callback
* operation is carried out by ra_upgrade_legacy_daemons_cb(). If the
* daemon was not upgraded, we need to mark the legacy-routing:ipv4[6]
* instance to be enabled (by routeadm -e), since it now must run the
* un-upgradeable legacy daemon.
*
* routeadm -l fmri
*
* Lists all properties and values in the routing property group associated
* with instance fmri. We simply walk through the composed property
* group, displaying all values. See ra_list_props_cb().
*
* routeadm -m fmri key=value ...
*
* Modify property values in the routing property group. If the same
* key is used more than once, multiple property values are set for that
* property. Properties must exist in the composed property group, but
* will only ever be set at the instance level to prevent multiple
* instances inheriting the property in error. See ra_modify_props_cb().
*
* routeadm -s var=value
*
* In all cases bar the routing-svcs variable, this simply involves
* setting the appropriate SMF property value for the variable. The
* routing-svcs case is more complex, since we would like operations
* like the following to have intuitive effects:
* # routeadm -s routing-svcs=route -e ipv4-routing -u
* # routeadm -s routing-svcs=rdisc -u
* i.e., in the end, rdisc is the only routing service running. To
* accomplish this switchover, we need to disable the old routing-svcs
* and enable the new, marking the latter with the curr-routing-svc
* property so that routeadm -e will pick them up. This is carried
* out by the ra_update_routing_svcs() function.
*
* routeadm -R alt_root ...
*
* Used to support use of routeadm in Custom Jumpstart scripts, this
* option causes all subsequent commands to be appended to the
* /var/svc/profile/upgrade file, which is run on the subsequent boot.
* This is done because the SMF repository is not available to make
* the modifications to property values required in routeadm operations.
*
* routeadm -u
*
* Update applies the "next boot" state to the current system. Here
* we simply take the persistent state (general/enabled value) and
* make it the current state through smf_enable_instance() or
* smf_disable_instance() as appropriate (these calls, without the
* temporary flag set, delete the general_ovr/enabled property).
*/
#define RA_OPT_IPV4_ROUTING "ipv4-routing"
#define RA_OPT_IPV6_ROUTING "ipv6-routing"
#define RA_OPT_IPV4_FORWARDING "ipv4-forwarding"
#define RA_OPT_IPV6_FORWARDING "ipv6-forwarding"
#define IS_ROUTING_OPT(opt) (strcmp(opt, RA_OPT_IPV4_ROUTING) == 0 || \
strcmp(opt, RA_OPT_IPV6_ROUTING) == 0)
#define RA_VAR_IPV4_ROUTING_DAEMON "ipv4-routing-daemon"
#define RA_VAR_IPV4_ROUTING_DAEMON_ARGS "ipv4-routing-daemon-args"
#define RA_VAR_IPV4_ROUTING_STOP_CMD "ipv4-routing-stop-cmd"
#define RA_VAR_IPV6_ROUTING_DAEMON "ipv6-routing-daemon"
#define RA_VAR_IPV6_ROUTING_DAEMON_ARGS "ipv6-routing-daemon-args"
#define RA_VAR_IPV6_ROUTING_STOP_CMD "ipv6-routing-stop-cmd"
#define RA_VAR_ROUTING_SVCS "routing-svcs"
#define RA_INSTANCE_ALL NULL
#define RA_INSTANCE_ROUTING_SETUP "svc:/network/routing-setup:default"
#define RA_INSTANCE_IPV4_FORWARDING "svc:/network/ipv4-forwarding:default"
#define RA_INSTANCE_IPV6_FORWARDING "svc:/network/ipv6-forwarding:default"
#define RA_INSTANCE_LEGACY_ROUTING_IPV4 \
"svc:/network/routing/legacy-routing:ipv4"
#define RA_INSTANCE_LEGACY_ROUTING_IPV6 \
"svc:/network/routing/legacy-routing:ipv6"
#define RA_INSTANCE_NDP "svc:/network/routing/ndp:default"
#define RA_PG_ROUTEADM "routeadm"
#define RA_PROP_CURR_ROUTING_SVC "current-routing-svc"
#define RA_PROP_ROUTING_SVCS "routing-svcs"
#define RA_PROP_DEFAULT_ROUTING_SVCS "default-routing-svcs"
#define RA_PROP_PROTO "protocol"
#define RA_PROP_DAEMON "daemon"
#define RA_PROP_DEFAULT_DAEMON "default-daemon"
#define RA_PROP_DAEMON_ARGS "daemon-args"
#define RA_PROP_DEFAULT_DAEMON_ARGS "default-daemon-args"
#define RA_PROP_DAEMON_STOP_CMD "daemon-stop-cmd"
#define RA_PROP_DEFAULT_STOP_CMD "default-daemon"
#define RA_PROP_LEGACY_DAEMON "legacy-daemon"
#define RA_PROP_DEFAULT_IPV4_ROUTING "default-ipv4-routing"
#define RA_PROP_DEFAULT_IPV6_ROUTING "default-ipv6-routing"
#define RA_PROP_DEFAULT_IPV4_FORWARDING "default-ipv4-forwarding"
#define RA_PROP_DEFAULT_IPV6_FORWARDING "default-ipv6-forwarding"
#define RA_PROP_IPV4_ROUTING_SET "ipv4-routing-set"
#define RA_PROP_IPV6_ROUTING_SET "ipv6-routing-set"
#define RA_PROP_ROUTING_CONF_READ "routing-conf-read"
#define RA_PG_ROUTING "routing"
#define RA_PROPVAL_BOOLEAN_TRUE "true"
#define RA_PROPVAL_BOOLEAN_FALSE "false"
#define RA_PROPVAL_PROTO_IPV4 "ipv4"
#define RA_PROPVAL_PROTO_IPV6 "ipv6"
#define RA_SVC_FLAG_NONE 0x0
#define RA_SVC_FLAG_IPV4_ROUTING 0x1
#define RA_SVC_FLAG_IPV6_ROUTING 0x2
#define RA_SMF_UPGRADE_FILE "/var/svc/profile/upgrade"
#define RA_SMF_UPGRADE_MSG " # added by routeadm(8)"
#define RA_CONF_FILE "/etc/inet/routing.conf"
#define RA_CONF_FILE_OLD "/etc/inet/routing.conf.old"
#define RA_MAX_CONF_LINE 256
/*
* Option value. Each option requires an FMRI identifying which services
* to run the get_current/persistent scf_walk_fmri() function with, and
* associated flags (to ensure that in the case that multiple services
* match, we select the correct ones). In addition, we specify the FMRI
* and property used to set default option value. The opt_enabled field
* is used to hold retrieved state from get_*_opt_() callbacks and to specify
* desired state for set_*_opt() operations.
*/
typedef struct raopt {
const char *opt_name;
const char *opt_fmri;
int opt_flags;
boolean_t opt_enabled;
const char *opt_default_fmri;
const char *opt_default_prop;
boolean_t opt_default_enabled;
} raopt_t;
raopt_t ra_opts[] = {
{ RA_OPT_IPV4_ROUTING, RA_INSTANCE_ALL, RA_SVC_FLAG_IPV4_ROUTING,
B_FALSE, RA_INSTANCE_ROUTING_SETUP, RA_PROP_DEFAULT_IPV4_ROUTING,
B_FALSE },
{ RA_OPT_IPV6_ROUTING, RA_INSTANCE_ALL, RA_SVC_FLAG_IPV6_ROUTING,
B_FALSE, RA_INSTANCE_ROUTING_SETUP, RA_PROP_DEFAULT_IPV6_ROUTING,
B_FALSE },
{ RA_OPT_IPV4_FORWARDING, RA_INSTANCE_IPV4_FORWARDING, RA_SVC_FLAG_NONE,
B_FALSE, RA_INSTANCE_IPV4_FORWARDING, RA_PROP_DEFAULT_IPV4_FORWARDING,
B_FALSE },
{ RA_OPT_IPV6_FORWARDING, RA_INSTANCE_IPV6_FORWARDING, RA_SVC_FLAG_NONE,
B_FALSE, RA_INSTANCE_IPV6_FORWARDING, RA_PROP_DEFAULT_IPV6_FORWARDING,
B_FALSE },
{ NULL, NULL, RA_SVC_FLAG_NONE, B_FALSE, NULL, NULL, B_FALSE }
};
typedef enum option_values {
OPT_INVALID, OPT_ENABLED, OPT_DISABLED, OPT_DEFAULT, OPT_UNKNOWN
} oval_t;
typedef struct ra_var {
const char *var_name;
const char *var_fmri;
const char *var_prop;
char *var_value;
const char *var_default_fmri;
const char *var_default_prop;
char *var_default_value;
} ravar_t;
ravar_t ra_vars[] = {
{ RA_VAR_IPV4_ROUTING_DAEMON, RA_INSTANCE_LEGACY_ROUTING_IPV4,
RA_PROP_DAEMON, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV4,
RA_PROP_DEFAULT_DAEMON, NULL},
{ RA_VAR_IPV4_ROUTING_DAEMON_ARGS, RA_INSTANCE_LEGACY_ROUTING_IPV4,
RA_PROP_DAEMON_ARGS, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV4,
RA_PROP_DEFAULT_DAEMON_ARGS, NULL },
{ RA_VAR_IPV4_ROUTING_STOP_CMD, RA_INSTANCE_LEGACY_ROUTING_IPV4,
RA_PROP_DAEMON_STOP_CMD, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV4,
RA_PROP_DEFAULT_STOP_CMD, NULL },
{ RA_VAR_IPV6_ROUTING_DAEMON, RA_INSTANCE_LEGACY_ROUTING_IPV6,
RA_PROP_DAEMON, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV6,
RA_PROP_DEFAULT_DAEMON, NULL },
{ RA_VAR_IPV6_ROUTING_DAEMON_ARGS, RA_INSTANCE_LEGACY_ROUTING_IPV6,
RA_PROP_DAEMON_ARGS, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV6,
RA_PROP_DEFAULT_DAEMON_ARGS, NULL },
{ RA_VAR_IPV6_ROUTING_STOP_CMD, RA_INSTANCE_LEGACY_ROUTING_IPV6,
RA_PROP_DAEMON_STOP_CMD, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV6,
RA_PROP_DEFAULT_STOP_CMD, NULL },
{ RA_VAR_ROUTING_SVCS, RA_INSTANCE_ROUTING_SETUP,
RA_PROP_ROUTING_SVCS, NULL, RA_INSTANCE_ROUTING_SETUP,
RA_PROP_DEFAULT_ROUTING_SVCS, NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
char *v_opt[] = {
#define IPV4_ROUTING_DAEMON 0
RA_VAR_IPV4_ROUTING_DAEMON,
#define IPV4_ROUTING_DAEMON_ARGS 1
RA_VAR_IPV4_ROUTING_DAEMON_ARGS,
#define IPV4_ROUTING_STOP_CMD 2
RA_VAR_IPV4_ROUTING_STOP_CMD,
#define IPV6_ROUTING_DAEMON 3
RA_VAR_IPV6_ROUTING_DAEMON,
#define IPV6_ROUTING_DAEMON_ARGS 4
RA_VAR_IPV6_ROUTING_DAEMON_ARGS,
#define IPV6_ROUTING_STOP_CMD 5
RA_VAR_IPV6_ROUTING_STOP_CMD,
#define ROUTING_SVCS 6
RA_VAR_ROUTING_SVCS,
NULL
};
#define IS_IPV4_VAR(varname) (strncmp(varname, "ipv4", 4) == 0)
#define IS_IPV6_VAR(varname) (strncmp(varname, "ipv6", 4) == 0)
#define VAR_PROTO_MATCH(varname, proto) (strncmp(varname, proto, 4) == 0)
#define IPV4_VARS_UNSET \
(strtok(ra_vars[IPV4_ROUTING_DAEMON].var_value, " \t") == NULL && \
strtok(ra_vars[IPV4_ROUTING_DAEMON_ARGS].var_value, " \t") == NULL && \
strtok(ra_vars[IPV4_ROUTING_STOP_CMD].var_value, " \t") == NULL)
#define IPV6_VARS_UNSET \
(strtok(ra_vars[IPV6_ROUTING_DAEMON].var_value, " \t") == NULL && \
strtok(ra_vars[IPV6_ROUTING_DAEMON_ARGS].var_value, " \t") == NULL && \
strtok(ra_vars[IPV6_ROUTING_STOP_CMD].var_value, " \t") == NULL)
/*
* Structure used in modify operations to tie property name and multiple values
* together.
*/
typedef struct ra_prop {
char *prop_name;
char **prop_values;
int prop_numvalues;
} ra_prop_t;
typedef int (*ra_smf_cb_t)(void *, scf_walkinfo_t *);
/* Used to store program name */
static const char *myname;
static void usage(void);
static int ra_check_legacy_daemons(void);
static int ra_upgrade_legacy_daemons(void);
static int ra_upgrade_cmd(char, int, char **);
static int ra_update(void);
static int ra_update_routing_svcs(char *);
static int ra_report(boolean_t, const char *);
static int ra_smf_cb(ra_smf_cb_t, const char *, void *);
static int ra_upgrade_from_legacy_conf(void);
static int ra_numv6intfs(void);
static int ra_parseconf(void);
static int ra_parseopt(char *, int, raopt_t *);
static int ra_parsevar(char *, ravar_t *);
static oval_t ra_str2oval(const char *);
static raopt_t *ra_str2opt(const char *);
static void ra_resetopts(void);
static ravar_t *ra_str2var(const char *);
static void ra_resetvars(const char *);
static char *ra_intloptname(const char *);
/* Callback for upgrade of legacy daemons */
static int ra_upgrade_legacy_daemons_cb(void *, scf_walkinfo_t *);
/* Callbacks used to set/retieve routing options */
static int ra_set_current_opt_cb(void *, scf_walkinfo_t *);
static int ra_set_persistent_opt_cb(void *, scf_walkinfo_t *);
static int ra_set_default_opt_cb(void *, scf_walkinfo_t *);
static int ra_get_current_opt_cb(void *, scf_walkinfo_t *);
static int ra_get_persistent_opt_cb(void *, scf_walkinfo_t *);
static int ra_get_default_opt_cb(void *, scf_walkinfo_t *);
static int ra_get_set_opt_common_cb(raopt_t *, scf_walkinfo_t *, boolean_t,
boolean_t);
static int ra_routing_opt_set_cb(void *, scf_walkinfo_t *);
static int ra_routing_opt_unset_cb(void *, scf_walkinfo_t *);
static int ra_routing_opt_set_unset_cb(raopt_t *, scf_walkinfo_t *, boolean_t);
/* Callbacks used to set/retrieve routing variables */
static int ra_set_persistent_var_cb(void *, scf_walkinfo_t *);
static int ra_get_persistent_var_cb(void *, scf_walkinfo_t *);
static int ra_get_default_var_cb(void *, scf_walkinfo_t *);
static int ra_mark_routing_svcs_cb(void *, scf_walkinfo_t *);
/* Callbacks used to list/set daemon properties and list daemons and states. */
static int ra_list_props_cb(void *, scf_walkinfo_t *);
static int ra_modify_props_cb(void *, scf_walkinfo_t *);
static int ra_print_state_cb(void *, scf_walkinfo_t *);
/* Utility functions for SMF operations */
static int ra_get_pg(scf_handle_t *, scf_instance_t *, const char *,
boolean_t, boolean_t, scf_propertygroup_t **);
static int ra_get_boolean_prop(scf_handle_t *, scf_instance_t *,
const char *, const char *, boolean_t, boolean_t, boolean_t *);
static int ra_get_single_prop_as_string(scf_handle_t *, scf_instance_t *,
const char *, const char *, boolean_t, boolean_t, scf_type_t *, char **);
static int ra_get_prop_as_string(scf_handle_t *, scf_instance_t *,
const char *, const char *, boolean_t, boolean_t, scf_type_t *, int *,
char ***);
static void ra_free_prop_values(int, char **);
static int ra_set_boolean_prop(scf_handle_t *, scf_instance_t *,
const char *, const char *, boolean_t, boolean_t);
static int ra_set_prop_from_string(scf_handle_t *, scf_instance_t *,
const char *, const char *, scf_type_t, boolean_t, int,
const char **);
static void
usage(void)
{
(void) fprintf(stderr, gettext(
"usage: %1$s [-p] [-R ]\n"
" %1$s [-e