13048Samaguire /*
23048Samaguire * CDDL HEADER START
33048Samaguire *
43048Samaguire * The contents of this file are subject to the terms of the
53048Samaguire * Common Development and Distribution License (the "License").
63048Samaguire * You may not use this file except in compliance with the License.
73048Samaguire *
83048Samaguire * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93048Samaguire * or http://www.opensolaris.org/os/licensing.
103048Samaguire * See the License for the specific language governing permissions
113048Samaguire * and limitations under the License.
123048Samaguire *
133048Samaguire * When distributing Covered Code, include this CDDL HEADER in each
143048Samaguire * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153048Samaguire * If applicable, add the following below this CDDL HEADER, with the
163048Samaguire * fields enclosed by brackets "[]" replaced with your own identifying
173048Samaguire * information: Portions Copyright [yyyy] [name of copyright owner]
183048Samaguire *
193048Samaguire * CDDL HEADER END
203048Samaguire */
213048Samaguire /*
223048Samaguire * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
233048Samaguire * Use is subject to license terms.
243048Samaguire */
253048Samaguire
263048Samaguire #pragma ident "%Z%%M% %I% %E% SMI"
273048Samaguire
283048Samaguire #include <stdio.h>
293048Samaguire #include <string.h>
303048Samaguire #include <stdlib.h>
313048Samaguire #include <unistd.h>
323048Samaguire #include <limits.h>
333048Samaguire #include <ctype.h>
343048Samaguire #include <stropts.h>
353048Samaguire #include <errno.h>
363048Samaguire #include <libintl.h>
373048Samaguire #include <locale.h>
383048Samaguire #include <fcntl.h>
393048Samaguire #include <sys/types.h>
403048Samaguire #include <sys/stat.h>
413094Samaguire #include <sys/socket.h>
423094Samaguire #include <sys/sockio.h>
433094Samaguire #include <inet/ip.h>
443094Samaguire #include <inet/nd.h>
453094Samaguire #include <net/if.h>
463048Samaguire #include <libscf.h>
473048Samaguire #include <libscf_priv.h>
483048Samaguire #include <libuutil.h>
493048Samaguire
503048Samaguire /*
513048Samaguire * This program moves routing management under SMF. We do this by giving
523048Samaguire * routeadm options that allow interaction with SMF services. These include:
533048Samaguire * - setting the routing services routeadm will enable
543048Samaguire * # routeadm -s routing-svcs="fmri [fmri...]"
553048Samaguire * where each fmri is an SMF routing service.
563048Samaguire * - changing properties of routing services
573048Samaguire * # routeadm -m fmri key=value [key=value...]
583048Samaguire * - listing routing daemon properties
593048Samaguire * # routeadm -l fmri
603048Samaguire * where all properties in the "routing" property group are listed.
613048Samaguire *
623048Samaguire * By providing legacy routing services (legacy-routing:ipv4 and ipv6), we
633048Samaguire * can also support running of routing daemons with no SMF service under SMF.
643048Samaguire * Specifying a routing daemon with no SMF counterpart results in the
653048Samaguire * daemon, it`s arguments and stop command being set in the appropriate instance
663048Samaguire * to be picked up by start/stop methods.
673048Samaguire *
683048Samaguire * Internally, routeadm keeps track of routing services by setting the
693048Samaguire * "current-routing-svc" property to "true" in the services it manages.
703048Samaguire * So for example, running
713048Samaguire * # routeadm -s routing-svcs="route:default ripng:default"
723048Samaguire * sets this variable in each instance specified. If the user specifies a
733048Samaguire * non-SMF routing daemon via
743048Samaguire * # routeadm -s ipv4-routing-daemon=/usr/sbin/mydaemon
753048Samaguire * the variable will be set for the legacy-routing:ipv4 instance.
763048Samaguire *
773048Samaguire * In order to ensure that the SMF versions of routing daemons are used
783048Samaguire * where possible, routeadm will check the daemons specified in
793048Samaguire * ipv4-routing-daemon/ipv6-routing-daemon to determine if there is an
803048Samaguire * SMF counterpart. If so, rather than running the legacy service
813048Samaguire * we move configuration, specifically the associated daemon arguments
823048Samaguire * to the SMF counterpart. From there, when the daemon is enabled, it
833048Samaguire * will pick up the daemon arguments setting, transfer the argument string
843048Samaguire * to the appropriate properties and run the service.
853048Samaguire *
863048Samaguire * To support the semantics of routeadm -e (enable at next boot) through SMF,
873048Samaguire * we make use of temporary state changes, which last only until reboot.
883048Samaguire * For example, if a service is disabled, and it is to be enabled via
893048Samaguire * routeadm -e, we simply change the disable to a temporary disable,
903048Samaguire * and set the persistent enabled value to true. This ensures the daemon
913048Samaguire * will run at next boot, but not now. The reverse is true for disabling
923048Samaguire * enabled instances (and if the daemon is enabled when we issue the enable,
933048Samaguire * we do nothing since it is already in the desired state).
943048Samaguire *
953048Samaguire * Since the code is quite involved, we provide a guide to the more complex
963048Samaguire * actions taken in response to user commands.
973048Samaguire *
983048Samaguire * routeadm -e[d] ipv4[6]-routing[forwarding]
993048Samaguire *
1003048Samaguire * In this case, the goal is to prepare the configured routing daemons
1013048Samaguire * (specified through routeadm -s routing-svcs="...") or forwarding
1023048Samaguire * services to switch on (-e) or of (-d) at next boot.
1033048Samaguire *
1043048Samaguire * Since this operation must be applied to multiple services in the
1053048Samaguire * routing daemon case (as opposed to the single ipv4[6]-forwarding
1063048Samaguire * service), we make use of the scf_walk_fmri() function, which
1073048Samaguire * applies a callback function to all matching functions. In the case
1083048Samaguire * of the routing daemons, we pass in a NULL signifying that all
1093048Samaguire * instances should be walked (we then weed out the relevant routing
1103048Samaguire * services through presence of the routeadm/protocol property). In
1113048Samaguire * the case of enable, a routing service is enabled IFF it has the
1123048Samaguire * previously-mentioned property - with an appropriate value (i.e. ipv4
1133048Samaguire * for "routeadm -e ipv4-routing") - and it has routeadm/curr-routing-svc
1143048Samaguire * property set to true (this is set by other operations such as
1153048Samaguire * routeadm -s routing-svcs="..."). Then, smf_enable_instance() or
1163048Samaguire * smf_disable_instance() is called, setting the temporary state to
1173048Samaguire * the current state of the service. This then allows setting of
1183048Samaguire * general/enabled value to next-boot value. In the case of disabling
1193048Samaguire * ipv4[6]-routing, all valid ipv4[6] routing daemons are prepared
1203048Samaguire * for next-boot disable, not just those specified via routing-svcs (this
1213048Samaguire * means that if the user enables routing daemons with "svcadm enable",
1223048Samaguire * disabling global routing does really switch off all routing daemons).
1233048Samaguire *
1243048Samaguire * This is implemented through the ra_get_set_opt_common_cb() function,
1253048Samaguire * called by the ra_set_persistent_opt_cb() function. The same
1263048Samaguire * function can be used for both routing and forwarding options, in the
1273048Samaguire * latter case we simply provide the specific FMRI of the forwarding
1283048Samaguire * service in question (ipv4-forwarding or ipv6-forwarding), and dispense
1293048Samaguire * with the eligibility tests we need to weed out the routing services
1303048Samaguire * from the rest.
1313048Samaguire *
1323048Samaguire * Before we initiate the "enable" however, we must check routing daemons
1333048Samaguire * specified via the legacy variables (ipv4-routing-daemon etc).
1343048Samaguire * If they map to SMF routing services, we wish to transfer their
1353048Samaguire * configuration to the corresponding services and use them instead of
1363048Samaguire * the legacy services. To do this, we need to match the daemon program
1373048Samaguire * against the routeadm/daemon property of each routing daemon (we use
1383048Samaguire * scf_walk_fmri() and the routeadm/protocol property again to identify
1393048Samaguire * daemons). If a match is found, the daemon arguments are transferred
1403048Samaguire * to the appropriate service`s daemon-args property, to be picked up
1413048Samaguire * by it`s start method and converted into appropriate property values.
1423048Samaguire * This is accomplished by ra_check_legacy_daemons(), and the callback
1433048Samaguire * operation is carried out by ra_upgrade_legacy_daemons_cb(). If the
1443048Samaguire * daemon was not upgraded, we need to mark the legacy-routing:ipv4[6]
1453048Samaguire * instance to be enabled (by routeadm -e), since it now must run the
1463048Samaguire * un-upgradeable legacy daemon.
1473048Samaguire *
1483048Samaguire * routeadm -l fmri
1493048Samaguire *
1503048Samaguire * Lists all properties and values in the routing property group associated
1513048Samaguire * with instance fmri. We simply walk through the composed property
1523048Samaguire * group, displaying all values. See ra_list_props_cb().
1533048Samaguire *
1543048Samaguire * routeadm -m fmri key=value ...
1553048Samaguire *
1563048Samaguire * Modify property values in the routing property group. If the same
1573048Samaguire * key is used more than once, multiple property values are set for that
1583048Samaguire * property. Properties must exist in the composed property group, but
1593048Samaguire * will only ever be set at the instance level to prevent multiple
1603048Samaguire * instances inheriting the property in error. See ra_modify_props_cb().
1613048Samaguire *
1623048Samaguire * routeadm -s var=value
1633048Samaguire *
1643048Samaguire * In all cases bar the routing-svcs variable, this simply involves
1653048Samaguire * setting the appropriate SMF property value for the variable. The
1663048Samaguire * routing-svcs case is more complex, since we would like operations
1673048Samaguire * like the following to have intuitive effects:
1683048Samaguire * # routeadm -s routing-svcs=route -e ipv4-routing -u
1693048Samaguire * # routeadm -s routing-svcs=rdisc -u
1703048Samaguire * i.e., in the end, rdisc is the only routing service running. To
1713048Samaguire * accomplish this switchover, we need to disable the old routing-svcs
1723048Samaguire * and enable the new, marking the latter with the curr-routing-svc
1733048Samaguire * property so that routeadm -e will pick them up. This is carried
1743048Samaguire * out by the ra_update_routing_svcs() function.
1753048Samaguire *
1763048Samaguire * routeadm -R alt_root ...
1773048Samaguire *
1783048Samaguire * Used to support use of routeadm in Custom Jumpstart scripts, this
1793048Samaguire * option causes all subsequent commands to be appended to the
1803048Samaguire * /var/svc/profile/upgrade file, which is run on the subsequent boot.
1813048Samaguire * This is done because the SMF repository is not available to make
1823048Samaguire * the modifications to property values required in routeadm operations.
1833048Samaguire *
1843048Samaguire * routeadm -u
1853048Samaguire *
1863048Samaguire * Update applies the "next boot" state to the current system. Here
1873048Samaguire * we simply take the persistent state (general/enabled value) and
1883048Samaguire * make it the current state through smf_enable_instance() or
1893048Samaguire * smf_disable_instance() as appropriate (these calls, without the
1903048Samaguire * temporary flag set, delete the general_ovr/enabled property).
1913048Samaguire */
1923048Samaguire
1933048Samaguire #define RA_OPT_IPV4_ROUTING "ipv4-routing"
1943048Samaguire #define RA_OPT_IPV6_ROUTING "ipv6-routing"
1953048Samaguire #define RA_OPT_IPV4_FORWARDING "ipv4-forwarding"
1963048Samaguire #define RA_OPT_IPV6_FORWARDING "ipv6-forwarding"
1973048Samaguire
1983048Samaguire #define IS_ROUTING_OPT(opt) (strcmp(opt, RA_OPT_IPV4_ROUTING) == 0 || \
1993048Samaguire strcmp(opt, RA_OPT_IPV6_ROUTING) == 0)
2003048Samaguire
2013048Samaguire #define RA_VAR_IPV4_ROUTING_DAEMON "ipv4-routing-daemon"
2023048Samaguire #define RA_VAR_IPV4_ROUTING_DAEMON_ARGS "ipv4-routing-daemon-args"
2033048Samaguire #define RA_VAR_IPV4_ROUTING_STOP_CMD "ipv4-routing-stop-cmd"
2043048Samaguire #define RA_VAR_IPV6_ROUTING_DAEMON "ipv6-routing-daemon"
2053048Samaguire #define RA_VAR_IPV6_ROUTING_DAEMON_ARGS "ipv6-routing-daemon-args"
2063048Samaguire #define RA_VAR_IPV6_ROUTING_STOP_CMD "ipv6-routing-stop-cmd"
2073048Samaguire #define RA_VAR_ROUTING_SVCS "routing-svcs"
2083048Samaguire
2093048Samaguire
2103048Samaguire #define RA_INSTANCE_ALL NULL
2113048Samaguire #define RA_INSTANCE_ROUTING_SETUP "svc:/network/routing-setup:default"
2123048Samaguire #define RA_INSTANCE_IPV4_FORWARDING "svc:/network/ipv4-forwarding:default"
2133048Samaguire #define RA_INSTANCE_IPV6_FORWARDING "svc:/network/ipv6-forwarding:default"
2143048Samaguire #define RA_INSTANCE_LEGACY_ROUTING_IPV4 \
2153048Samaguire "svc:/network/routing/legacy-routing:ipv4"
2163048Samaguire #define RA_INSTANCE_LEGACY_ROUTING_IPV6 \
2173048Samaguire "svc:/network/routing/legacy-routing:ipv6"
2183094Samaguire #define RA_INSTANCE_NDP "svc:/network/routing/ndp:default"
2193048Samaguire
2203048Samaguire #define RA_PG_ROUTEADM "routeadm"
2213048Samaguire #define RA_PROP_CURR_ROUTING_SVC "current-routing-svc"
2223048Samaguire #define RA_PROP_ROUTING_SVCS "routing-svcs"
2233048Samaguire #define RA_PROP_DEFAULT_ROUTING_SVCS "default-routing-svcs"
2243048Samaguire #define RA_PROP_PROTO "protocol"
2253048Samaguire #define RA_PROP_DAEMON "daemon"
2263048Samaguire #define RA_PROP_DEFAULT_DAEMON "default-daemon"
2273048Samaguire #define RA_PROP_DAEMON_ARGS "daemon-args"
2283048Samaguire #define RA_PROP_DEFAULT_DAEMON_ARGS "default-daemon-args"
2293048Samaguire #define RA_PROP_DAEMON_STOP_CMD "daemon-stop-cmd"
2303048Samaguire #define RA_PROP_DEFAULT_STOP_CMD "default-daemon"
2313048Samaguire #define RA_PROP_LEGACY_DAEMON "legacy-daemon"
2323048Samaguire #define RA_PROP_DEFAULT_IPV4_ROUTING "default-ipv4-routing"
2333048Samaguire #define RA_PROP_DEFAULT_IPV6_ROUTING "default-ipv6-routing"
2343048Samaguire #define RA_PROP_DEFAULT_IPV4_FORWARDING "default-ipv4-forwarding"
2353048Samaguire #define RA_PROP_DEFAULT_IPV6_FORWARDING "default-ipv6-forwarding"
2363048Samaguire #define RA_PROP_IPV4_ROUTING_SET "ipv4-routing-set"
2373048Samaguire #define RA_PROP_IPV6_ROUTING_SET "ipv6-routing-set"
2383048Samaguire #define RA_PROP_ROUTING_CONF_READ "routing-conf-read"
2393048Samaguire
2403048Samaguire #define RA_PG_ROUTING "routing"
2413048Samaguire
2423048Samaguire #define RA_PROPVAL_BOOLEAN_TRUE "true"
2433048Samaguire #define RA_PROPVAL_BOOLEAN_FALSE "false"
2443048Samaguire #define RA_PROPVAL_PROTO_IPV4 "ipv4"
2453048Samaguire #define RA_PROPVAL_PROTO_IPV6 "ipv6"
2463048Samaguire
2473048Samaguire #define RA_SVC_FLAG_NONE 0x0
2483048Samaguire #define RA_SVC_FLAG_IPV4_ROUTING 0x1
2493048Samaguire #define RA_SVC_FLAG_IPV6_ROUTING 0x2
2503048Samaguire
2513048Samaguire #define RA_SMF_UPGRADE_FILE "/var/svc/profile/upgrade"
2523048Samaguire #define RA_SMF_UPGRADE_MSG " # added by routeadm(1M)"
2533048Samaguire #define RA_CONF_FILE "/etc/inet/routing.conf"
2543048Samaguire #define RA_CONF_FILE_OLD "/etc/inet/routing.conf.old"
2553048Samaguire #define RA_MAX_CONF_LINE 256
2563048Samaguire
2573048Samaguire /*
2583048Samaguire * Option value. Each option requires an FMRI identifying which services
2593048Samaguire * to run the get_current/persistent scf_walk_fmri() function with, and
2603048Samaguire * associated flags (to ensure that in the case that multiple services
2613048Samaguire * match, we select the correct ones). In addition, we specify the FMRI
2623048Samaguire * and property used to set default option value. The opt_enabled field
2633048Samaguire * is used to hold retrieved state from get_*_opt_() callbacks and to specify
2643048Samaguire * desired state for set_*_opt() operations.
2653048Samaguire */
2663048Samaguire
2673048Samaguire typedef struct raopt {
2683048Samaguire const char *opt_name;
2693048Samaguire const char *opt_fmri;
2703048Samaguire int opt_flags;
2713048Samaguire boolean_t opt_enabled;
2723048Samaguire const char *opt_default_fmri;
2733048Samaguire const char *opt_default_prop;
2743048Samaguire boolean_t opt_default_enabled;
2753048Samaguire } raopt_t;
2763048Samaguire
2773048Samaguire
2783048Samaguire raopt_t ra_opts[] = {
2793048Samaguire { RA_OPT_IPV4_ROUTING, RA_INSTANCE_ALL, RA_SVC_FLAG_IPV4_ROUTING,
2803048Samaguire B_FALSE, RA_INSTANCE_ROUTING_SETUP, RA_PROP_DEFAULT_IPV4_ROUTING,
2813048Samaguire B_FALSE },
2823048Samaguire { RA_OPT_IPV6_ROUTING, RA_INSTANCE_ALL, RA_SVC_FLAG_IPV6_ROUTING,
2833048Samaguire B_FALSE, RA_INSTANCE_ROUTING_SETUP, RA_PROP_DEFAULT_IPV6_ROUTING,
2843048Samaguire B_FALSE },
2853048Samaguire { RA_OPT_IPV4_FORWARDING, RA_INSTANCE_IPV4_FORWARDING, RA_SVC_FLAG_NONE,
2863048Samaguire B_FALSE, RA_INSTANCE_IPV4_FORWARDING, RA_PROP_DEFAULT_IPV4_FORWARDING,
2873048Samaguire B_FALSE },
2883048Samaguire { RA_OPT_IPV6_FORWARDING, RA_INSTANCE_IPV6_FORWARDING, RA_SVC_FLAG_NONE,
2893048Samaguire B_FALSE, RA_INSTANCE_IPV6_FORWARDING, RA_PROP_DEFAULT_IPV6_FORWARDING,
2903048Samaguire B_FALSE },
2913048Samaguire { NULL, NULL, RA_SVC_FLAG_NONE, B_FALSE, NULL, NULL, B_FALSE }
2923048Samaguire };
2933048Samaguire
2943048Samaguire typedef enum option_values {
2953048Samaguire OPT_INVALID, OPT_ENABLED, OPT_DISABLED, OPT_DEFAULT, OPT_UNKNOWN
2963048Samaguire } oval_t;
2973048Samaguire
2983048Samaguire typedef struct ra_var {
2993048Samaguire const char *var_name;
3003048Samaguire const char *var_fmri;
3013048Samaguire const char *var_prop;
3023048Samaguire char *var_value;
3033048Samaguire const char *var_default_fmri;
3043048Samaguire const char *var_default_prop;
3053048Samaguire char *var_default_value;
3063048Samaguire } ravar_t;
3073048Samaguire
3083048Samaguire ravar_t ra_vars[] = {
3093048Samaguire { RA_VAR_IPV4_ROUTING_DAEMON, RA_INSTANCE_LEGACY_ROUTING_IPV4,
3103048Samaguire RA_PROP_DAEMON, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV4,
3113048Samaguire RA_PROP_DEFAULT_DAEMON, NULL},
3123048Samaguire { RA_VAR_IPV4_ROUTING_DAEMON_ARGS, RA_INSTANCE_LEGACY_ROUTING_IPV4,
3133048Samaguire RA_PROP_DAEMON_ARGS, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV4,
3143048Samaguire RA_PROP_DEFAULT_DAEMON_ARGS, NULL },
3153048Samaguire { RA_VAR_IPV4_ROUTING_STOP_CMD, RA_INSTANCE_LEGACY_ROUTING_IPV4,
3163048Samaguire RA_PROP_DAEMON_STOP_CMD, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV4,
3173048Samaguire RA_PROP_DEFAULT_STOP_CMD, NULL },
3183048Samaguire { RA_VAR_IPV6_ROUTING_DAEMON, RA_INSTANCE_LEGACY_ROUTING_IPV6,
3193048Samaguire RA_PROP_DAEMON, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV6,
3203048Samaguire RA_PROP_DEFAULT_DAEMON, NULL },
3213048Samaguire { RA_VAR_IPV6_ROUTING_DAEMON_ARGS, RA_INSTANCE_LEGACY_ROUTING_IPV6,
3223048Samaguire RA_PROP_DAEMON_ARGS, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV6,
3233048Samaguire RA_PROP_DEFAULT_DAEMON_ARGS, NULL },
3243048Samaguire { RA_VAR_IPV6_ROUTING_STOP_CMD, RA_INSTANCE_LEGACY_ROUTING_IPV6,
3253048Samaguire RA_PROP_DAEMON_STOP_CMD, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV6,
3263048Samaguire RA_PROP_DEFAULT_STOP_CMD, NULL },
3273048Samaguire { RA_VAR_ROUTING_SVCS, RA_INSTANCE_ROUTING_SETUP,
3283048Samaguire RA_PROP_ROUTING_SVCS, NULL, RA_INSTANCE_ROUTING_SETUP,
3293048Samaguire RA_PROP_DEFAULT_ROUTING_SVCS, NULL },
3303048Samaguire { NULL, NULL, NULL, NULL, NULL, NULL, NULL }
3313048Samaguire };
3323048Samaguire
3333048Samaguire char *v_opt[] = {
3343048Samaguire #define IPV4_ROUTING_DAEMON 0
3353048Samaguire RA_VAR_IPV4_ROUTING_DAEMON,
3363048Samaguire #define IPV4_ROUTING_DAEMON_ARGS 1
3373048Samaguire RA_VAR_IPV4_ROUTING_DAEMON_ARGS,
3383048Samaguire #define IPV4_ROUTING_STOP_CMD 2
3393048Samaguire RA_VAR_IPV4_ROUTING_STOP_CMD,
3403048Samaguire #define IPV6_ROUTING_DAEMON 3
3413048Samaguire RA_VAR_IPV6_ROUTING_DAEMON,
3423048Samaguire #define IPV6_ROUTING_DAEMON_ARGS 4
3433048Samaguire RA_VAR_IPV6_ROUTING_DAEMON_ARGS,
3443048Samaguire #define IPV6_ROUTING_STOP_CMD 5
3453048Samaguire RA_VAR_IPV6_ROUTING_STOP_CMD,
3463048Samaguire #define ROUTING_SVCS 6
3473048Samaguire RA_VAR_ROUTING_SVCS,
3483048Samaguire NULL
3493048Samaguire };
3503048Samaguire
3513048Samaguire #define IS_IPV4_VAR(varname) (strncmp(varname, "ipv4", 4) == 0)
3523048Samaguire #define IS_IPV6_VAR(varname) (strncmp(varname, "ipv6", 4) == 0)
3533048Samaguire #define VAR_PROTO_MATCH(varname, proto) (strncmp(varname, proto, 4) == 0)
3543048Samaguire #define IPV4_VARS_UNSET \
3553048Samaguire (strtok(ra_vars[IPV4_ROUTING_DAEMON].var_value, " \t") == NULL && \
3563048Samaguire strtok(ra_vars[IPV4_ROUTING_DAEMON_ARGS].var_value, " \t") == NULL && \
3573048Samaguire strtok(ra_vars[IPV4_ROUTING_STOP_CMD].var_value, " \t") == NULL)
3583048Samaguire
3593048Samaguire #define IPV6_VARS_UNSET \
3603048Samaguire (strtok(ra_vars[IPV6_ROUTING_DAEMON].var_value, " \t") == NULL && \
3613048Samaguire strtok(ra_vars[IPV6_ROUTING_DAEMON_ARGS].var_value, " \t") == NULL && \
3623048Samaguire strtok(ra_vars[IPV6_ROUTING_STOP_CMD].var_value, " \t") == NULL)
3633048Samaguire
3643048Samaguire /*
3653048Samaguire * Structure used in modify operations to tie property name and multiple values
3663048Samaguire * together.
3673048Samaguire */
3683048Samaguire typedef struct ra_prop {
3693048Samaguire char *prop_name;
3703048Samaguire char **prop_values;
3713048Samaguire int prop_numvalues;
3723048Samaguire } ra_prop_t;
3733048Samaguire
3743048Samaguire typedef int (*ra_smf_cb_t)(void *, scf_walkinfo_t *);
3753048Samaguire
3763048Samaguire /* Used to store program name */
3773048Samaguire static const char *myname;
3783048Samaguire
3793048Samaguire static void usage(void);
3803048Samaguire
3813048Samaguire static int ra_check_legacy_daemons(void);
3823048Samaguire static int ra_upgrade_legacy_daemons(void);
3833048Samaguire static int ra_upgrade_cmd(char, int, char **);
3843048Samaguire static int ra_update(void);
3853048Samaguire static int ra_update_routing_svcs(char *);
3863048Samaguire static int ra_report(boolean_t, const char *);
3873048Samaguire static int ra_smf_cb(ra_smf_cb_t, const char *, void *);
3883048Samaguire static int ra_upgrade_from_legacy_conf(void);
3893094Samaguire static int ra_numv6intfs(void);
3903048Samaguire static int ra_parseconf(void);
3913048Samaguire static int ra_parseopt(char *, int, raopt_t *);
3923048Samaguire static int ra_parsevar(char *, ravar_t *);
3933048Samaguire static oval_t ra_str2oval(const char *);
3943048Samaguire static raopt_t *ra_str2opt(const char *);
3953048Samaguire static void ra_resetopts(void);
3963048Samaguire static ravar_t *ra_str2var(const char *);
3973048Samaguire static void ra_resetvars(const char *);
3983048Samaguire static char *ra_intloptname(const char *);
3993048Samaguire
4003048Samaguire /* Callback for upgrade of legacy daemons */
4013048Samaguire static int ra_upgrade_legacy_daemons_cb(void *, scf_walkinfo_t *);
4023048Samaguire
4033048Samaguire /* Callbacks used to set/retieve routing options */
4043048Samaguire static int ra_set_current_opt_cb(void *, scf_walkinfo_t *);
4053048Samaguire static int ra_set_persistent_opt_cb(void *, scf_walkinfo_t *);
4063048Samaguire static int ra_set_default_opt_cb(void *, scf_walkinfo_t *);
4073048Samaguire static int ra_get_current_opt_cb(void *, scf_walkinfo_t *);
4083048Samaguire static int ra_get_persistent_opt_cb(void *, scf_walkinfo_t *);
4093048Samaguire static int ra_get_default_opt_cb(void *, scf_walkinfo_t *);
4103048Samaguire static int ra_get_set_opt_common_cb(raopt_t *, scf_walkinfo_t *, boolean_t,
4113048Samaguire boolean_t);
412*3294Samaguire static int ra_routing_opt_set_cb(void *, scf_walkinfo_t *);
413*3294Samaguire static int ra_routing_opt_unset_cb(void *, scf_walkinfo_t *);
414*3294Samaguire static int ra_routing_opt_set_unset_cb(raopt_t *, scf_walkinfo_t *, boolean_t);
4153048Samaguire
4163048Samaguire /* Callbacks used to set/retrieve routing variables */
4173048Samaguire static int ra_set_persistent_var_cb(void *, scf_walkinfo_t *);
4183048Samaguire static int ra_get_persistent_var_cb(void *, scf_walkinfo_t *);
4193048Samaguire static int ra_get_default_var_cb(void *, scf_walkinfo_t *);
4203048Samaguire static int ra_mark_routing_svcs_cb(void *, scf_walkinfo_t *);
4213048Samaguire
4223048Samaguire /* Callbacks used to list/set daemon properties and list daemons and states. */
4233048Samaguire static int ra_list_props_cb(void *, scf_walkinfo_t *);
4243048Samaguire static int ra_modify_props_cb(void *, scf_walkinfo_t *);
4253048Samaguire static int ra_print_state_cb(void *, scf_walkinfo_t *);
4263048Samaguire
4273048Samaguire /* Utility functions for SMF operations */
4283048Samaguire static int ra_get_pg(scf_handle_t *, scf_instance_t *, const char *,
4293048Samaguire boolean_t, boolean_t, scf_propertygroup_t **);
4303048Samaguire static int ra_get_boolean_prop(scf_handle_t *, scf_instance_t *,
4313048Samaguire const char *, const char *, boolean_t, boolean_t, boolean_t *);
4323048Samaguire static int ra_get_single_prop_as_string(scf_handle_t *, scf_instance_t *,
4333048Samaguire const char *, const char *, boolean_t, boolean_t, scf_type_t *, char **);
4343048Samaguire static int ra_get_prop_as_string(scf_handle_t *, scf_instance_t *,
4353048Samaguire const char *, const char *, boolean_t, boolean_t, scf_type_t *, int *,
4363048Samaguire char ***);
4373048Samaguire static void ra_free_prop_values(int, char **);
4383048Samaguire static int ra_set_boolean_prop(scf_handle_t *, scf_instance_t *,
4393048Samaguire const char *, const char *, boolean_t, boolean_t);
4403048Samaguire static int ra_set_prop_from_string(scf_handle_t *, scf_instance_t *,
4413048Samaguire const char *, const char *, scf_type_t, boolean_t, int,
4423048Samaguire const char **);
4433048Samaguire
4443048Samaguire static void
usage(void)4453048Samaguire usage(void)
4463048Samaguire {
4473048Samaguire (void) fprintf(stderr, gettext(
4483048Samaguire "usage: %1$s [-p] [-R <root-dir>]\n"
4493048Samaguire " %1$s [-e <option>] [-d <option>] [-r <option>]\n"
4503048Samaguire " [-l <FMRI>] [-m <FMRI> key=value [...]]\n"
4513048Samaguire " [-s <var>=<val>] [-R <root-dir>]\n"
4523048Samaguire " %1$s -u\n\n"
4533048Samaguire " <option> is one of:\n"
4543048Samaguire " ipv4-forwarding\n"
4553048Samaguire " ipv4-routing\n"
4563048Samaguire " ipv6-forwarding\n"
4573048Samaguire " ipv6-routing\n\n"
4583048Samaguire " <var> is one of:\n"
4593048Samaguire " ipv4-routing-daemon\n"
4603048Samaguire " ipv4-routing-daemon-args\n"
4613048Samaguire " ipv4-routing-stop-cmd\n"
4623048Samaguire " ipv6-routing-daemon\n"
4633048Samaguire " ipv6-routing-daemon-args\n"
4643048Samaguire " ipv6-routing-stop-cmd\n"
4653048Samaguire " routing-svcs\n"), myname);
4663048Samaguire }
4673048Samaguire
4683048Samaguire int
main(int argc,char * argv[])4693048Samaguire main(int argc, char *argv[])
4703048Samaguire {
4713048Samaguire int opt, opt_index, numargs, status = 0;
4723048Samaguire int numvalues, i;
4733048Samaguire ssize_t keylen;
4743048Samaguire boolean_t modify = B_FALSE, report = B_TRUE, update = B_FALSE;
475*3294Samaguire boolean_t booting = B_FALSE, alt_root_set = B_FALSE;
4763048Samaguire boolean_t parseable = B_FALSE;
4773048Samaguire char *key, *nk, *keyend, *val, **vals, *options, *fmri;
4783048Samaguire char *parseopt = NULL;
4793048Samaguire raopt_t *raopt;
4803048Samaguire ravar_t *ravar;
4813048Samaguire ra_prop_t raprop;
4823048Samaguire
4833048Samaguire myname = argv[0];
4843048Samaguire
4853048Samaguire (void) setlocale(LC_ALL, "");
4863048Samaguire
4873048Samaguire #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
4883048Samaguire #define TEXT_DOMAIN "SYS_TEST"
4893048Samaguire #endif
4903048Samaguire
4913048Samaguire (void) textdomain(TEXT_DOMAIN);
4923048Samaguire
4933048Samaguire /*
4943048Samaguire * Before processing any options, we parse /etc/inet/routing.conf
4953048Samaguire * (if present) and transfer values to SMF.
4963048Samaguire */
4973048Samaguire if (ra_upgrade_from_legacy_conf() == -1)
4983048Samaguire exit(EXIT_FAILURE);
499*3294Samaguire while ((opt = getopt(argc, argv, ":bd:e:l:m:p:R:r:s:u")) != EOF) {
5003048Samaguire switch (opt) {
501*3294Samaguire case 'b':
502*3294Samaguire /*
503*3294Samaguire * Project-private option that tells us enable/disable
504*3294Samaguire * operations should not set ipv4(6)-routing-set
505*3294Samaguire * property. Used in routing-setup service method
506*3294Samaguire * to change default routing state, and, if
507*3294Samaguire * no explicit enable/disable operations have been
508*3294Samaguire * carried out, change current ipv4 routing state.
509*3294Samaguire */
510*3294Samaguire booting = B_TRUE;
511*3294Samaguire break;
5123048Samaguire case 'd':
5133048Samaguire case 'e':
5143048Samaguire case 'r':
5153048Samaguire if (alt_root_set) {
5163048Samaguire if (ra_upgrade_cmd(opt, 1, &optarg) != 0)
5173048Samaguire exit(EXIT_FAILURE);
5183048Samaguire modify = B_TRUE;
5193048Samaguire break;
5203048Samaguire }
5213048Samaguire if ((raopt = ra_str2opt(optarg)) != NULL) {
5223048Samaguire /* Set current value appropriately */
5233048Samaguire switch (opt) {
5243048Samaguire case 'd':
5253048Samaguire raopt->opt_enabled = B_FALSE;
5263048Samaguire break;
5273048Samaguire case 'e':
5283048Samaguire /*
5293048Samaguire * Check legacy daemons, mark
5303048Samaguire * routing-svcs.
5313048Samaguire */
5323048Samaguire if (IS_ROUTING_OPT(optarg) &&
5333048Samaguire ra_check_legacy_daemons() == -1)
5343048Samaguire exit(EXIT_FAILURE);
5353048Samaguire raopt->opt_enabled = B_TRUE;
5363048Samaguire break;
5373048Samaguire case 'r':
5383048Samaguire /*
5393048Samaguire * This callback sets opt_enabled to
5403048Samaguire * the default value.
5413048Samaguire */
5423048Samaguire ra_resetopts();
5433048Samaguire if (ra_smf_cb(ra_get_default_opt_cb,
5443048Samaguire raopt->opt_default_fmri, raopt)
5453048Samaguire == -1)
5463048Samaguire exit(EXIT_FAILURE);
5473048Samaguire if (raopt->opt_enabled &&
5483048Samaguire IS_ROUTING_OPT(optarg) &&
5493048Samaguire ra_check_legacy_daemons() == -1)
5503048Samaguire exit(EXIT_FAILURE);
5513048Samaguire /* set value to default */
5523048Samaguire raopt->opt_enabled =
5533048Samaguire raopt->opt_default_enabled;
5543048Samaguire break;
5553048Samaguire }
5563048Samaguire if (ra_smf_cb(ra_set_persistent_opt_cb,
5573048Samaguire raopt->opt_fmri, raopt) == -1)
5583048Samaguire exit(EXIT_FAILURE);
559*3294Samaguire /*
560*3294Samaguire * ipv4(6)-routing explicitly enabled/disabled,
561*3294Samaguire * need to set ipv4(6)-routing-set property
562*3294Samaguire * for routing-setup service. Once this
563*3294Samaguire * is set, routing-setup will not override
564*3294Samaguire * administrator action and will not enable
565*3294Samaguire * ipv4-routing in the case that no default
566*3294Samaguire * route can be determined. If ipv4(6)-routing
567*3294Samaguire * is reverted to its default value, set
568*3294Samaguire * ipv4(6)-routing-set back to false.
569*3294Samaguire */
570*3294Samaguire if (!booting && (raopt->opt_flags &
571*3294Samaguire (RA_SVC_FLAG_IPV4_ROUTING |
572*3294Samaguire RA_SVC_FLAG_IPV6_ROUTING))) {
573*3294Samaguire if (ra_smf_cb(opt == 'r' ?
574*3294Samaguire ra_routing_opt_unset_cb :
575*3294Samaguire ra_routing_opt_set_cb,
576*3294Samaguire raopt->opt_default_fmri, raopt)
577*3294Samaguire == -1)
578*3294Samaguire exit(EXIT_FAILURE);
579*3294Samaguire }
5803048Samaguire } else if ((ravar = ra_str2var(optarg)) != NULL) {
5813048Samaguire if (opt != 'r') {
5823048Samaguire usage();
5833048Samaguire exit(EXIT_FAILURE);
5843048Samaguire }
5853048Samaguire /* set current value to default */
5863048Samaguire ra_resetopts();
5873048Samaguire if (ra_smf_cb(ra_get_default_var_cb,
5883048Samaguire ravar->var_default_fmri, ravar) == -1)
5893048Samaguire exit(EXIT_FAILURE);
5903048Samaguire /* Need special case for routing-svcs var */
5913048Samaguire if (strcmp(ravar->var_name, RA_VAR_ROUTING_SVCS)
5923048Samaguire == 0) {
5933048Samaguire if (ra_update_routing_svcs(
5943048Samaguire ravar->var_default_value) == -1)
5953048Samaguire exit(EXIT_FAILURE);
5963048Samaguire } else if (ra_smf_cb(ra_set_persistent_var_cb,
5973048Samaguire ravar->var_fmri, ravar) == -1)
5983048Samaguire exit(EXIT_FAILURE);
5993048Samaguire } else {
6003048Samaguire (void) fprintf(stderr, gettext(
6013048Samaguire "%1$s: invalid option: %2$s\n"), myname,
6023048Samaguire optarg);
6033048Samaguire usage();
6043048Samaguire exit(EXIT_FAILURE);
6053048Samaguire }
6063048Samaguire modify = B_TRUE;
6073048Samaguire break;
6083048Samaguire case 'l':
6093048Samaguire if (ra_smf_cb(ra_list_props_cb, optarg, NULL) == -1)
6103048Samaguire exit(EXIT_FAILURE);
6113048Samaguire report = B_FALSE;
6123048Samaguire break;
6133048Samaguire case 'm':
6143048Samaguire fmri = optarg;
6153048Samaguire modify = B_TRUE;
6163048Samaguire /*
6173048Samaguire * Argument list of key=value pairs, we need to
6183048Samaguire * collate all matching keys to set multiple values.
6193048Samaguire */
6203048Samaguire numargs = 1;
6213048Samaguire i = optind;
6223048Samaguire for (numargs = 1; argv[i] != NULL && argv[i][0] != '-';
6233048Samaguire numargs++)
6243048Samaguire i++;
6253048Samaguire if (numargs == 1) {
6263048Samaguire (void) fprintf(stderr, gettext(
6273048Samaguire "%s: key=value required for "
6283048Samaguire "property change\n"), myname);
6293048Samaguire usage();
6303048Samaguire exit(EXIT_FAILURE);
6313048Samaguire }
6323048Samaguire if (alt_root_set) {
6333048Samaguire if (ra_upgrade_cmd(opt, numargs,
6343048Samaguire &argv[optind - 1]) == -1)
6353048Samaguire exit(EXIT_FAILURE);
6363048Samaguire optind += numargs - 1;
6373048Samaguire break;
6383048Samaguire }
6393048Samaguire /*
6403048Samaguire * Collect all key=value pairs which use same key
6413048Samaguire * so we can add multiple property values.
6423048Samaguire */
6433048Samaguire for (key = argv[optind]; key != NULL && key[0] != '-';
6443048Samaguire key = argv[++optind]) {
6453048Samaguire if (key[0] == '\0')
6463048Samaguire continue;
6473048Samaguire vals = malloc(sizeof (char *));
6483048Samaguire if ((vals[0] = strchr(key, '=')) == NULL) {
6493048Samaguire (void) fprintf(stderr, gettext(
6503048Samaguire "%s: Malformed name=value "
6513048Samaguire "pair %s\n"), myname, key);
6523048Samaguire exit(EXIT_FAILURE);
6533048Samaguire }
6543048Samaguire numvalues = 1;
6553048Samaguire *(vals[0]) = '\0';
6563048Samaguire (vals[0])++;
6573048Samaguire i = optind + 1;
6583048Samaguire for (nk = argv[i];
6593048Samaguire nk != NULL && nk[0] != '-';
6603048Samaguire nk = argv[++i]) {
6613048Samaguire if (nk[0] == '\0')
6623048Samaguire continue;
6633048Samaguire if ((keyend = strchr(nk, '='))
6643048Samaguire == NULL) {
6653048Samaguire (void) fprintf(stderr, gettext(
6663048Samaguire "%s: Malformed name=value "
6673048Samaguire " pair %s\n"), myname, nk);
6683048Samaguire exit(EXIT_FAILURE);
6693048Samaguire }
6703048Samaguire if ((keylen = keyend - nk) !=
6713048Samaguire strlen(key))
6723048Samaguire continue;
6733048Samaguire if (strncmp(key, nk, keylen) == 0) {
6743048Samaguire vals = realloc(vals, ++numvalues
6753048Samaguire * sizeof (char *));
6763048Samaguire vals[numvalues - 1] = ++keyend;
6773048Samaguire nk[0] = '\0';
6783048Samaguire optind++;
6793048Samaguire }
6803048Samaguire }
6813048Samaguire raprop.prop_name = key;
6823048Samaguire raprop.prop_values = vals;
6833048Samaguire raprop.prop_numvalues = numvalues;
6843048Samaguire if (ra_smf_cb(ra_modify_props_cb, fmri,
6853048Samaguire &raprop) == -1)
6863048Samaguire exit(EXIT_FAILURE);
6873048Samaguire }
6883048Samaguire break;
6893048Samaguire case 'p':
6903048Samaguire parseable = B_TRUE;
6913048Samaguire parseopt = optarg;
6923048Samaguire break;
6933048Samaguire case 'R':
6943048Samaguire if (chroot(optarg) == -1) {
6953048Samaguire (void) fprintf(stderr, gettext(
6963048Samaguire "%1$s: failed to chroot to %2$s: %3$s\n"),
6973048Samaguire myname, optarg, strerror(errno));
6983048Samaguire exit(EXIT_FAILURE);
6993048Samaguire }
7003048Samaguire alt_root_set = B_TRUE;
7013048Samaguire report = B_FALSE;
7023048Samaguire break;
7033048Samaguire case 's':
7043048Samaguire if (alt_root_set) {
7053048Samaguire if (ra_upgrade_cmd(opt, 1, &optarg) == -1)
7063048Samaguire exit(EXIT_FAILURE);
7073048Samaguire modify = B_TRUE;
7083048Samaguire break;
7093048Samaguire }
7103048Samaguire options = optarg;
7113048Samaguire while (*options != '\0') {
7123048Samaguire opt_index = getsubopt(&options, v_opt, &val);
7133048Samaguire if (val == NULL) {
7143048Samaguire usage();
7153048Samaguire exit(EXIT_FAILURE);
7163048Samaguire }
7173048Samaguire if (opt_index == -1) {
7183048Samaguire (void) fprintf(stderr, gettext(
7193048Samaguire "%1$s: invalid variable: %2$s\n"),
7203048Samaguire myname, optarg);
7213048Samaguire usage();
7223048Samaguire exit(EXIT_FAILURE);
7233048Samaguire }
7243048Samaguire ravar = &ra_vars[opt_index];
7253048Samaguire /* Need special case for routing-svcs var */
7263048Samaguire if (strcmp(ravar->var_name, RA_VAR_ROUTING_SVCS)
7273048Samaguire == 0) {
7283048Samaguire if (ra_update_routing_svcs(val) == -1)
7293048Samaguire return (-1);
7303048Samaguire } else {
7313048Samaguire ravar->var_value = strdup(val);
7323048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb,
7333048Samaguire ravar->var_fmri, ravar) == -1)
7343048Samaguire exit(EXIT_FAILURE);
7353048Samaguire }
7363048Samaguire }
7373048Samaguire modify = B_TRUE;
7383048Samaguire break;
7393048Samaguire case 'u':
7403048Samaguire update = B_TRUE;
7413048Samaguire break;
7423048Samaguire case ':':
7433048Samaguire /* if not 'p', usage failure */
7443048Samaguire if (strcmp(argv[optind - 1], "-p") != 0) {
7453048Samaguire (void) fprintf(stderr, gettext(
7463048Samaguire "%s: option requires an argument -%s\n"),
7473048Samaguire myname, argv[optind - 1]);
7483048Samaguire usage();
7493048Samaguire exit(EXIT_FAILURE);
7503048Samaguire }
7513048Samaguire parseable = B_TRUE;
7523048Samaguire break;
7533048Samaguire case '?':
7543048Samaguire usage();
7553048Samaguire exit(EXIT_FAILURE);
7563048Samaguire }
7573048Samaguire }
7583048Samaguire
7593048Samaguire if (argc > optind) {
7603048Samaguire /* There shouldn't be any extra args. */
7613048Samaguire usage();
7623048Samaguire exit(EXIT_FAILURE);
7633048Samaguire }
7643048Samaguire
7653048Samaguire if (parseable && (update || modify)) {
7663048Samaguire (void) fprintf(stderr, gettext("%s: the -p option cannot be "
7673048Samaguire "used with any of -demrsu\n"), myname);
7683048Samaguire usage();
7693048Samaguire exit(EXIT_FAILURE);
7703048Samaguire }
7713048Samaguire
7723048Samaguire if (update && ! alt_root_set)
7733048Samaguire status = ra_update();
7743048Samaguire
7753048Samaguire if (report && !modify && !update)
7763048Samaguire status = ra_report(parseable, parseopt);
7773048Samaguire
7783048Samaguire return (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
7793048Samaguire }
7803048Samaguire
7813048Samaguire /*
7823048Samaguire * Upgrade legacy daemons, mark to-be-enabled routing services.
7833048Samaguire */
7843048Samaguire static int
ra_check_legacy_daemons(void)7853048Samaguire ra_check_legacy_daemons(void)
7863048Samaguire {
7873048Samaguire ravar_t *routing_svcs = ra_str2var(RA_VAR_ROUTING_SVCS);
7883048Samaguire ravar_t *v4d = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON);
7893048Samaguire ravar_t *v6d = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON);
7903048Samaguire char *fmri, *nextfmri;
7913048Samaguire boolean_t mark = B_FALSE;
7923048Samaguire
7933048Samaguire if (ra_smf_cb(ra_get_persistent_var_cb, routing_svcs->var_fmri,
7943048Samaguire routing_svcs) == -1)
7953048Samaguire return (-1);
7963048Samaguire
7973048Samaguire /* First unmark all services */
7983048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, NULL, &mark) == -1)
7993048Samaguire return (-1);
8003048Samaguire
8013048Samaguire mark = B_TRUE;
8023048Samaguire if (routing_svcs->var_value != NULL) {
8033048Samaguire /*
8043048Samaguire * For routing-svcs variable, mark each named
8053048Samaguire * service as a current-routing-svc.
8063048Samaguire */
8073048Samaguire if ((fmri = strdup(routing_svcs->var_value)) == NULL) {
8083048Samaguire (void) fprintf(stderr, gettext(
8093048Samaguire "%s: out of memory\n"), myname);
8103048Samaguire return (-1);
8113048Samaguire }
8123048Samaguire /* Now, mark each service named in routing-svcs. */
8133048Samaguire for (nextfmri = strtok(fmri, " \t");
8143048Samaguire nextfmri != NULL;
8153048Samaguire nextfmri = strtok(NULL, " \t")) {
8163048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, nextfmri,
8173048Samaguire &mark) == -1) {
8183048Samaguire free(fmri);
8193048Samaguire return (-1);
8203048Samaguire }
8213048Samaguire }
8223048Samaguire free(fmri);
8233048Samaguire }
8243048Samaguire
8253048Samaguire /*
8263048Samaguire * Now check if legacy variables (if specified) map to SMF routing
8273048Samaguire * daemons. If so, transfer associated daemon arguments.
8283048Samaguire */
8293048Samaguire if (ra_upgrade_legacy_daemons() == -1)
8303048Samaguire return (-1);
8313048Samaguire
8323048Samaguire ra_resetvars(NULL);
8333048Samaguire /*
8343048Samaguire * At this point, if the legacy services still have ipv4/ipv6
8353048Samaguire * routing daemons specified, we know they weren`t upgraded, so
8363048Samaguire * we mark them also.
8373048Samaguire */
8383048Samaguire if (ra_smf_cb(ra_get_persistent_var_cb, v4d->var_fmri, v4d) == -1 ||
8393048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v6d->var_fmri, v6d) == -1)
8403048Samaguire return (-1);
8413048Samaguire
8423048Samaguire if (v4d->var_value != NULL && strtok(v4d->var_value, " \t") != NULL &&
8433048Samaguire ra_smf_cb(ra_mark_routing_svcs_cb, RA_INSTANCE_LEGACY_ROUTING_IPV4,
8443048Samaguire &mark) == -1)
8453048Samaguire return (-1);
8463048Samaguire if (v6d->var_value != NULL && strtok(v6d->var_value, " \t") != NULL &&
8473048Samaguire ra_smf_cb(ra_mark_routing_svcs_cb, RA_INSTANCE_LEGACY_ROUTING_IPV6,
8483048Samaguire &mark) == -1)
8493048Samaguire return (-1);
8503048Samaguire
8513048Samaguire return (0);
8523048Samaguire }
8533048Samaguire
8543048Samaguire /*
8553048Samaguire * Retrieve legacy daemon variables, and check if any SMF routing daemons
8563048Samaguire * run the daemons specified. If so, the legacy configuration (arguments
8573048Samaguire * to the daemon) is transferred to the routeadm/daemon-args property
8583048Samaguire * of the corresponding instance. From there, the instance picks up the
8593048Samaguire * value and will transfer the daemon arguments to individiual properties
8603048Samaguire * when enabled.
8613048Samaguire */
8623048Samaguire static int
ra_upgrade_legacy_daemons(void)8633048Samaguire ra_upgrade_legacy_daemons(void)
8643048Samaguire {
8653048Samaguire ravar_t *v4d = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON);
8663048Samaguire ravar_t *v6d = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON);
8673048Samaguire ravar_t *v4args = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON_ARGS);
8683048Samaguire ravar_t *v6args = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON_ARGS);
8693048Samaguire ravar_t *v4stop = ra_str2var(RA_VAR_IPV4_ROUTING_STOP_CMD);
8703048Samaguire ravar_t *v6stop = ra_str2var(RA_VAR_IPV6_ROUTING_STOP_CMD);
8713048Samaguire
8723048Samaguire if (ra_smf_cb(ra_get_persistent_var_cb, v4d->var_fmri, v4d) == -1 ||
8733048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v6d->var_fmri, v6d) == -1 ||
8743048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v4args->var_fmri, v4args)
8753048Samaguire == -1 ||
8763048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v6args->var_fmri, v6args)
8773048Samaguire == -1 ||
8783048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v4stop->var_fmri, v4stop)
8793048Samaguire == -1 ||
8803048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v6stop->var_fmri, v6stop)
8813048Samaguire == -1)
8823048Samaguire return (-1);
8833048Samaguire
8843048Samaguire return (ra_smf_cb(ra_upgrade_legacy_daemons_cb, NULL, NULL));
8853048Samaguire }
8863048Samaguire
8873048Samaguire /*
8883048Samaguire * Determine if service runs the same daemon as that which is specified
8893048Samaguire * in ipv4-routing-daemon or ipv6-routing-daemon. If so, the associated
8903048Samaguire * daemon arguments are transferred to the service.
8913048Samaguire */
8923048Samaguire
8933048Samaguire /* ARGSUSED0 */
8943048Samaguire static int
ra_upgrade_legacy_daemons_cb(void * data,scf_walkinfo_t * wip)8953048Samaguire ra_upgrade_legacy_daemons_cb(void *data, scf_walkinfo_t *wip)
8963048Samaguire {
8973048Samaguire const char *inst_fmri = wip->fmri;
8983048Samaguire scf_instance_t *inst = wip->inst;
8993048Samaguire scf_handle_t *h = scf_instance_handle(inst);
9003048Samaguire char *daemon, *l_daemon = NULL;
9013048Samaguire ravar_t *v4d = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON);
9023048Samaguire ravar_t *v6d = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON);
9033048Samaguire ravar_t *v4args = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON_ARGS);
9043048Samaguire ravar_t *v6args = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON_ARGS);
9053048Samaguire ravar_t *v4stop = ra_str2var(RA_VAR_IPV4_ROUTING_STOP_CMD);
9063048Samaguire ravar_t *v6stop = ra_str2var(RA_VAR_IPV6_ROUTING_STOP_CMD);
9073048Samaguire ravar_t *routing_svcs = ra_str2var(RA_VAR_ROUTING_SVCS);
9083048Samaguire boolean_t mark, marked;
9093048Samaguire char *new_routing_svcs;
9103048Samaguire
9113048Samaguire /*
9123048Samaguire * Ensure instance is a routing service, and not one of the
9133048Samaguire * legacy instances - if it is, the daemon property is already
9143048Samaguire * set to the legacy daemon.
9153048Samaguire */
9163048Samaguire if (ra_get_single_prop_as_string(h, inst, RA_PG_ROUTEADM,
9173048Samaguire RA_PROP_DAEMON, B_TRUE, B_FALSE, NULL, &daemon) == -1 ||
9183048Samaguire strcmp(RA_INSTANCE_LEGACY_ROUTING_IPV4, inst_fmri) == 0 ||
9193048Samaguire strcmp(RA_INSTANCE_LEGACY_ROUTING_IPV6, inst_fmri) == 0)
9203048Samaguire return (0);
9213048Samaguire
9223048Samaguire /* A legacy daemon may be defined */
9233048Samaguire (void) ra_get_single_prop_as_string(h, inst, RA_PG_ROUTEADM,
9243048Samaguire RA_PROP_LEGACY_DAEMON, B_TRUE, B_FALSE, NULL, &l_daemon);
9253048Samaguire
9263048Samaguire /*
9273048Samaguire * If we match daemon/legacy_daemon with ipv4-routing-daemon or
9283048Samaguire * ipv6-routing-daemon values, transfer daemon-args value
9293048Samaguire * to the matching service.
9303048Samaguire */
9313048Samaguire if (v4d->var_value != NULL && (strcmp(v4d->var_value, daemon) == 0 ||
9323048Samaguire (l_daemon != NULL && strcmp(v4d->var_value, l_daemon) == 0))) {
9333048Samaguire (void) printf(gettext("%s: migrating daemon configuration "
9343048Samaguire "for %s to %s\n"), myname, l_daemon != NULL ?
9353048Samaguire l_daemon : daemon, inst_fmri);
9363048Samaguire /* Transfer daemon-args value, clear legacy v4 values */
9373048Samaguire if (ra_set_prop_from_string(h, inst, RA_PG_ROUTEADM,
9383048Samaguire RA_PROP_DAEMON_ARGS, SCF_TYPE_ASTRING, B_TRUE, 1,
9393048Samaguire (const char **)&(v4args->var_value)) == -1)
9403048Samaguire return (-1);
9413048Samaguire ra_resetvars(RA_PROPVAL_PROTO_IPV4);
9423048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb,
9433048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV4, v4d) == -1 ||
9443048Samaguire ra_smf_cb(ra_set_persistent_var_cb,
9453048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV4, v4args) == -1 ||
9463048Samaguire ra_smf_cb(ra_set_persistent_var_cb,
9473048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV4, v4stop) == -1)
9483048Samaguire return (-1);
9493048Samaguire } else if (v6d->var_value != NULL && (strcmp(v6d->var_value, daemon)
9503048Samaguire == 0 ||
9513048Samaguire (l_daemon != NULL && strcmp(v6d->var_value, l_daemon) == 0))) {
9523048Samaguire (void) printf(gettext("%s: migrating daemon configuration "
9533048Samaguire "for %s to %s\n"), myname, l_daemon != NULL ?
9543048Samaguire l_daemon : daemon, inst_fmri);
9553048Samaguire /* Transfer daemon-args value, clear legacy v6 values */
9563048Samaguire if (ra_set_prop_from_string(h, inst, RA_PG_ROUTEADM,
9573048Samaguire RA_PROP_DAEMON_ARGS, SCF_TYPE_ASTRING, B_TRUE, 1,
9583048Samaguire (const char **)&(v6args->var_value)) == -1)
9593048Samaguire return (-1);
9603048Samaguire ra_resetvars(RA_PROPVAL_PROTO_IPV6);
9613048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb,
9623048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV6, v6d) == -1 ||
9633048Samaguire ra_smf_cb(ra_set_persistent_var_cb,
9643048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV6, v6args) == -1 ||
9653048Samaguire ra_smf_cb(ra_set_persistent_var_cb,
9663048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV6, v6stop) == -1)
9673048Samaguire return (-1);
9683048Samaguire } else
9693048Samaguire return (0);
9703048Samaguire
9713048Samaguire /*
9723048Samaguire * If service is unmarked at this point, add it to routing-svcs and
9733048Samaguire * mark it.
9743048Samaguire */
9753048Samaguire if (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM,
9763048Samaguire RA_PROP_CURR_ROUTING_SVC, B_FALSE, B_FALSE, &marked) == -1 ||
9773048Samaguire marked == B_FALSE) {
9783048Samaguire mark = B_TRUE;
9793048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, inst_fmri, &mark)
9803048Samaguire == -1 ||
9813048Samaguire ra_smf_cb(ra_get_persistent_var_cb, routing_svcs->var_fmri,
9823048Samaguire routing_svcs) == -1)
9833048Samaguire return (-1);
9843048Samaguire if ((new_routing_svcs =
9853048Samaguire malloc(strlen(routing_svcs->var_value) +
9863048Samaguire strlen(inst_fmri) + 2)) == NULL) {
9873048Samaguire (void) fprintf(stderr, gettext(
9883048Samaguire "%s: out of memory"), myname);
9893048Samaguire return (-1);
9903048Samaguire }
9913048Samaguire if (strlen(routing_svcs->var_value) == 0)
9923048Samaguire (void) snprintf(new_routing_svcs,
9933048Samaguire strlen(inst_fmri) + 1, "%s", inst_fmri);
9943048Samaguire else
9953048Samaguire (void) snprintf(new_routing_svcs,
9963048Samaguire strlen(routing_svcs->var_value) +
9973048Samaguire strlen(inst_fmri) + 2, "%s %s",
9983048Samaguire routing_svcs->var_value, inst_fmri);
9993048Samaguire free(routing_svcs->var_value);
10003048Samaguire routing_svcs->var_value = new_routing_svcs;
10013048Samaguire (void) smf_refresh_instance(inst_fmri);
10023048Samaguire return (ra_smf_cb(ra_set_persistent_var_cb,
10033048Samaguire routing_svcs->var_fmri, routing_svcs));
10043048Samaguire }
10053048Samaguire (void) smf_refresh_instance(inst_fmri);
10063048Samaguire return (0);
10073048Samaguire }
10083048Samaguire
10093048Samaguire /*
10103048Samaguire * If we are upgrading, append operation to <alt_root>/var/svc/profile/upgrade.
10113048Samaguire */
10123048Samaguire static int
ra_upgrade_cmd(char opt,int argc,char ** argv)10133048Samaguire ra_upgrade_cmd(char opt, int argc, char **argv)
10143048Samaguire {
10153048Samaguire FILE *fp;
10163048Samaguire int i;
10173048Samaguire
10183048Samaguire if ((fp = fopen(RA_SMF_UPGRADE_FILE, "a+")) == NULL) {
10193048Samaguire (void) fprintf(stderr, gettext(
10203048Samaguire "%1$s: failed to open %2$s: %3$s\n"),
10213048Samaguire myname, RA_SMF_UPGRADE_FILE, strerror(errno));
10223048Samaguire return (-1);
10233048Samaguire }
10243048Samaguire (void) fprintf(fp, "/sbin/routeadm -%c ", opt);
10253048Samaguire if (argv != NULL) {
10263048Samaguire for (i = 0; i < argc; i++)
10273048Samaguire (void) fprintf(fp, "%s ", argv[i]);
10283048Samaguire }
10293048Samaguire (void) fprintf(fp, "%s\n", RA_SMF_UPGRADE_MSG);
10303048Samaguire (void) fclose(fp);
10313048Samaguire return (0);
10323048Samaguire }
10333048Samaguire
10343048Samaguire /*
10353048Samaguire * Set current state to "next boot" state, i.e. if general/enabled
10363048Samaguire * value is overlaid by a general_ovr/enabled value, set the current state
10373048Samaguire * to the value of the latter. Doing this applies "next boot" changes to
10383094Samaguire * the current setup. If any IPv6 interfaces are present, also start in.ndpd.
10393048Samaguire */
10403048Samaguire static int
ra_update(void)10413048Samaguire ra_update(void)
10423048Samaguire {
10433094Samaguire int i;
10443048Samaguire
10453048Samaguire if (ra_check_legacy_daemons() == -1)
10463048Samaguire return (-1);
10473048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) {
10483094Samaguire if (ra_smf_cb(ra_set_current_opt_cb, ra_opts[i].opt_fmri,
10493094Samaguire &ra_opts[i]) == -1) {
10503094Samaguire return (-1);
10513094Samaguire }
10523048Samaguire }
10533094Samaguire /*
10543094Samaguire * If in.ndpd isn't already running, then we start it here, regardless
10553094Samaguire * of global IPv6 routing status (provided there are IPv6 interfaces
10563094Samaguire * present).
10573094Samaguire */
10583094Samaguire if (ra_numv6intfs() > 0)
10593094Samaguire return (smf_enable_instance(RA_INSTANCE_NDP, SMF_TEMPORARY));
10603094Samaguire return (0);
10613048Samaguire }
10623048Samaguire
10633048Samaguire /*
10643048Samaguire * Here we catch the special case where ipv4/ipv6 routing was enabled,
10653048Samaguire * and the user updates the routing-svcs list. The problem is that
10663048Samaguire * the enabled state is the result of services on the old routing-svcs list
10673048Samaguire * being enabled, and we want to support users doing something like this:
10683048Samaguire *
10693048Samaguire * # routeadm -s routing-svcs=route -e ipv4-routing -u
10703048Samaguire *
10713048Samaguire * followed by
10723048Samaguire *
10733048Samaguire * # routeadm -s routing-svcs=rdisc -u
10743048Samaguire *
10753048Samaguire * To do this, we need to:
10763048Samaguire * - cache the old ipv4-routing/ipv6-routing values.
10773048Samaguire * - persistently disable the old routing-svcs list.
10783048Samaguire * - if ipv4-routing was enabled, mark and persistently enable all the new
10793048Samaguire * v4 routing-svcs
10803048Samaguire * - if ipv6-routing was enabled, mark and persistently enable all the new
10813048Samaguire * v6 routing-svcs.
10823048Samaguire * This will result in the next "-u" switching on the new routing-svcs, and
10833048Samaguire * switching off the old ones, as the user would expect.
10843048Samaguire */
10853048Samaguire static int
ra_update_routing_svcs(char * routing_svcs_new)10863048Samaguire ra_update_routing_svcs(char *routing_svcs_new)
10873048Samaguire {
10883048Samaguire raopt_t *v4opt = ra_str2opt(RA_OPT_IPV4_ROUTING);
10893048Samaguire raopt_t *v6opt = ra_str2opt(RA_OPT_IPV6_ROUTING);
10903048Samaguire ravar_t *routing_svcs = ra_str2var(RA_VAR_ROUTING_SVCS);
10913048Samaguire char *routing_svcs_old, *fmri;
10923048Samaguire boolean_t v4_old, v6_old, mark = B_FALSE;
10933048Samaguire
10943048Samaguire ra_resetopts();
10953048Samaguire if (ra_smf_cb(ra_get_persistent_opt_cb, v4opt->opt_fmri, v4opt) == -1 ||
10963048Samaguire ra_smf_cb(ra_get_persistent_opt_cb, v6opt->opt_fmri, v6opt) == -1 ||
10973048Samaguire ra_smf_cb(ra_get_persistent_var_cb, routing_svcs->var_fmri,
10983048Samaguire routing_svcs) == -1)
10993048Samaguire return (-1);
11003048Samaguire v4_old = v4opt->opt_enabled;
11013048Samaguire v6_old = v6opt->opt_enabled;
11023048Samaguire routing_svcs_old = routing_svcs->var_value;
11033048Samaguire routing_svcs->var_value = routing_svcs_new;
11043048Samaguire
11053048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb, routing_svcs->var_fmri,
11063048Samaguire routing_svcs) == -1) {
11073048Samaguire free(routing_svcs_old);
11083048Samaguire return (-1);
11093048Samaguire }
11103048Samaguire
11113048Samaguire if (!v4_old && !v6_old) {
11123048Samaguire /* We don`t need to do anything, since services were disabled */
11133048Samaguire free(routing_svcs_old);
11143048Samaguire return (0);
11153048Samaguire }
11163048Samaguire v4opt->opt_enabled = B_FALSE;
11173048Samaguire v6opt->opt_enabled = B_FALSE;
11183048Samaguire
11193048Samaguire /* Persistently disable each old v4/v6 "routing-svc" */
11203048Samaguire for (fmri = strtok(routing_svcs_old, " \t"); fmri != NULL;
11213048Samaguire fmri = strtok(NULL, " \t")) {
11223048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, fmri, &mark) == -1) {
11233048Samaguire free(routing_svcs_old);
11243048Samaguire return (-1);
11253048Samaguire }
11263048Samaguire if (v4_old &&
11273048Samaguire ra_smf_cb(ra_set_persistent_opt_cb, fmri, v4opt) == -1) {
11283048Samaguire free(routing_svcs_old);
11293048Samaguire return (-1);
11303048Samaguire }
11313048Samaguire if (v6_old &&
11323048Samaguire ra_smf_cb(ra_set_persistent_opt_cb, fmri, v6opt) == -1) {
11333048Samaguire free(routing_svcs_old);
11343048Samaguire return (-1);
11353048Samaguire }
11363048Samaguire }
11373048Samaguire free(routing_svcs_old);
11383048Samaguire v4opt->opt_enabled = v4_old;
11393048Samaguire v6opt->opt_enabled = v6_old;
11403048Samaguire
11413048Samaguire /* Persistently enable each new v4/v6 "routing-svc" */
11423048Samaguire mark = B_TRUE;
11433048Samaguire for (fmri = strtok(routing_svcs_new, " \t"); fmri != NULL;
11443048Samaguire fmri = strtok(NULL, " \t")) {
11453048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, fmri, &mark) == -1)
11463048Samaguire return (-1);
11473048Samaguire if (v4_old &&
11483048Samaguire ra_smf_cb(ra_set_persistent_opt_cb, fmri, v4opt) == -1)
11493048Samaguire return (-1);
11503048Samaguire if (v6_old &&
11513048Samaguire ra_smf_cb(ra_set_persistent_opt_cb, fmri, v6opt) == -1)
11523048Samaguire return (-1);
11533048Samaguire }
11543048Samaguire return (0);
11553048Samaguire }
11563048Samaguire
11573048Samaguire /*
11583048Samaguire * Display status, in parseable form if required. If param is
11593048Samaguire * specified, only the named option/variable is displayed (this option is
11603048Samaguire * for parseable display only).
11613048Samaguire */
11623048Samaguire static int
ra_report(boolean_t parseable,const char * param)11633048Samaguire ra_report(boolean_t parseable, const char *param)
11643048Samaguire {
11653048Samaguire int i;
11663048Samaguire char *c_state, *d_state, *p_state, *p_var, *d_var;
11673048Samaguire char *enabled = "enabled";
11683048Samaguire char *disabled = "disabled";
11693048Samaguire boolean_t param_found = B_FALSE;
11703048Samaguire
11713048Samaguire if (!parseable) {
11723048Samaguire (void) printf(gettext(
11733048Samaguire " Configuration Current "
11743048Samaguire "Current\n"
11753048Samaguire " Option Configuration "
11763048Samaguire "System State\n"
11773048Samaguire "---------------------------------------------------"
11783048Samaguire "------------\n"));
11793048Samaguire }
11803048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) {
11813048Samaguire if (param != NULL) {
11823048Samaguire if (strcmp(ra_opts[i].opt_name, param) == 0)
11833048Samaguire param_found = B_TRUE;
11843048Samaguire else
11853048Samaguire continue;
11863048Samaguire }
11873048Samaguire if (ra_smf_cb(ra_get_current_opt_cb,
11883048Samaguire ra_opts[i].opt_fmri, &ra_opts[i]) == -1)
11893048Samaguire return (-1);
11903048Samaguire c_state = ra_opts[i].opt_enabled ? enabled : disabled;
11913048Samaguire ra_resetopts();
11923048Samaguire if (ra_smf_cb(ra_get_persistent_opt_cb,
11933048Samaguire ra_opts[i].opt_fmri, &ra_opts[i]) == -1)
11943048Samaguire return (-1);
11953048Samaguire p_state = ra_opts[i].opt_enabled ? enabled : disabled;
11963048Samaguire ra_resetopts();
11973048Samaguire if (ra_smf_cb(ra_get_default_opt_cb,
11983048Samaguire ra_opts[i].opt_default_fmri, &ra_opts[i]) == -1)
11993048Samaguire return (-1);
12003048Samaguire d_state = ra_opts[i].opt_default_enabled ? enabled : disabled;
12013048Samaguire ra_resetopts();
12023048Samaguire if (parseable) {
12033048Samaguire if (param == NULL)
12043048Samaguire (void) printf("%s ", ra_opts[i].opt_name);
12053048Samaguire (void) printf("persistent=%s default=%s "
12063048Samaguire "current=%s\n", p_state, d_state, c_state);
12073048Samaguire } else {
12083048Samaguire (void) printf(gettext("%1$27s %2$-21s%3$s\n"),
12093048Samaguire ra_intloptname(ra_opts[i].opt_name),
12103048Samaguire p_state, c_state);
12113048Samaguire }
12123048Samaguire }
12133048Samaguire if (!parseable)
12143048Samaguire (void) printf("\n");
12153048Samaguire
12163048Samaguire ra_resetvars(NULL);
12173048Samaguire
12183048Samaguire /* Gather persistent/default variable values */
12193048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) {
12203048Samaguire if (ra_smf_cb(ra_get_persistent_var_cb,
12213048Samaguire ra_vars[i].var_fmri, &ra_vars[i]) == -1 ||
12223048Samaguire ra_smf_cb(ra_get_default_var_cb,
12233048Samaguire ra_vars[i].var_default_fmri, &ra_vars[i]) == -1)
12243048Samaguire return (-1);
12253048Samaguire
12263048Samaguire }
12273048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) {
12283048Samaguire if (param != NULL) {
12293048Samaguire if (strcmp(ra_vars[i].var_name, param) == 0)
12303048Samaguire param_found = B_TRUE;
12313048Samaguire else
12323048Samaguire continue;
12333048Samaguire }
12343048Samaguire p_var = ra_vars[i].var_value == NULL ? "":
12353048Samaguire ra_vars[i].var_value;
12363048Samaguire d_var = ra_vars[i].var_default_value == NULL ?
12373048Samaguire "": ra_vars[i].var_default_value;
12383048Samaguire if (parseable) {
12393048Samaguire if (param == NULL)
12403048Samaguire (void) printf("%s ", ra_vars[i].var_name);
12413048Samaguire (void) printf("persistent=\"%s\" "
12423048Samaguire "default=\"%s\" \n", p_var, d_var);
12433048Samaguire } else {
12443048Samaguire /* If daemon variables are not set, do not display. */
12453048Samaguire if ((IS_IPV4_VAR(ra_vars[i].var_name) &&
12463048Samaguire IPV4_VARS_UNSET) ||
12473048Samaguire (IS_IPV6_VAR(ra_vars[i].var_name) &&
12483048Samaguire IPV6_VARS_UNSET))
12493048Samaguire continue;
12503048Samaguire (void) printf(gettext("%1$27s \"%2$s\"\n"),
12513048Samaguire ra_intloptname(ra_vars[i].var_name), p_var);
12523048Samaguire }
12533048Samaguire }
12543048Samaguire
12553048Samaguire if (param != NULL && !param_found) {
12563048Samaguire (void) fprintf(stderr, gettext(
12573048Samaguire "%s: no such option/variable %s\n"), myname, param);
12583048Samaguire return (-1);
12593048Samaguire }
12603048Samaguire if (parseable)
12613048Samaguire return (0);
12623048Samaguire (void) printf(gettext("\nRouting daemons:\n"));
12633048Samaguire (void) printf("\n %s %s\n", "STATE", "FMRI");
12643048Samaguire if (ra_smf_cb(ra_print_state_cb, NULL, NULL) == -1)
12653048Samaguire return (-1);
12663048Samaguire return (0);
12673048Samaguire }
12683048Samaguire
12693048Samaguire /*
12703048Samaguire * Call scf_walk_fmri() with appropriate function, fmri, and data.
12713048Samaguire * A NULL fmri causes scf_walk_fmri() to run on all instances. We make
12723048Samaguire * use of this many times in applying changes to the routing services.
12733048Samaguire */
12743048Samaguire static int
ra_smf_cb(ra_smf_cb_t cbfunc,const char * fmri,void * data)12753048Samaguire ra_smf_cb(ra_smf_cb_t cbfunc, const char *fmri, void *data)
12763048Samaguire {
12773048Samaguire scf_handle_t *h;
12783048Samaguire int exit_status = 0;
12793048Samaguire
12803048Samaguire if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
12813048Samaguire scf_handle_bind(h) == -1) {
12823048Samaguire (void) fprintf(stderr, gettext(
12833048Samaguire "%s: cannot connect to SMF repository\n"), myname);
12843048Samaguire return (-1);
12853048Samaguire }
12863048Samaguire return (scf_walk_fmri(h, fmri == NULL ? 0 : 1,
12873048Samaguire fmri == NULL ? NULL : (char **)&fmri, 0,
12883048Samaguire cbfunc, data, &exit_status, uu_die));
12893048Samaguire }
12903048Samaguire
12913048Samaguire /*
12923048Samaguire * Applies persistent configuration settings to current setup.
12933048Samaguire */
12943048Samaguire static int
ra_set_current_opt_cb(void * data,scf_walkinfo_t * wip)12953048Samaguire ra_set_current_opt_cb(void *data, scf_walkinfo_t *wip)
12963048Samaguire {
12973048Samaguire return (ra_get_set_opt_common_cb(data, wip, B_FALSE, B_FALSE));
12983048Samaguire }
12993048Samaguire
13003048Samaguire /*
13013048Samaguire * Sets persistent value for option, to be applied on next boot
13023048Samaguire * or by "routeadm -u".
13033048Samaguire */
13043048Samaguire static int
ra_set_persistent_opt_cb(void * data,scf_walkinfo_t * wip)13053048Samaguire ra_set_persistent_opt_cb(void *data, scf_walkinfo_t *wip)
13063048Samaguire {
13073048Samaguire return (ra_get_set_opt_common_cb(data, wip, B_TRUE, B_FALSE));
13083048Samaguire }
13093048Samaguire
13103048Samaguire static int
ra_get_current_opt_cb(void * data,scf_walkinfo_t * wip)13113048Samaguire ra_get_current_opt_cb(void *data, scf_walkinfo_t *wip)
13123048Samaguire {
13133048Samaguire return (ra_get_set_opt_common_cb(data, wip, B_FALSE, B_TRUE));
13143048Samaguire }
13153048Samaguire
13163048Samaguire static int
ra_get_persistent_opt_cb(void * data,scf_walkinfo_t * wip)13173048Samaguire ra_get_persistent_opt_cb(void *data, scf_walkinfo_t *wip)
13183048Samaguire {
13193048Samaguire return (ra_get_set_opt_common_cb(data, wip, B_TRUE, B_TRUE));
13203048Samaguire }
13213048Samaguire
1322*3294Samaguire static int
ra_routing_opt_set_cb(void * data,scf_walkinfo_t * wip)1323*3294Samaguire ra_routing_opt_set_cb(void *data, scf_walkinfo_t *wip)
1324*3294Samaguire {
1325*3294Samaguire return (ra_routing_opt_set_unset_cb(data, wip, B_TRUE));
1326*3294Samaguire }
1327*3294Samaguire
1328*3294Samaguire static int
ra_routing_opt_unset_cb(void * data,scf_walkinfo_t * wip)1329*3294Samaguire ra_routing_opt_unset_cb(void *data, scf_walkinfo_t *wip)
1330*3294Samaguire {
1331*3294Samaguire return (ra_routing_opt_set_unset_cb(data, wip, B_FALSE));
1332*3294Samaguire }
1333*3294Samaguire
1334*3294Samaguire /*
1335*3294Samaguire * Notify network/routing-setup service that administrator has explicitly
1336*3294Samaguire * set/reset ipv4(6)-routing value. If no explicit setting of this value is
1337*3294Samaguire * done, ipv4-routing can be enabled in the situation when no default route can
1338*3294Samaguire * be determined.
1339*3294Samaguire */
1340*3294Samaguire static int
ra_routing_opt_set_unset_cb(raopt_t * raopt,scf_walkinfo_t * wip,boolean_t set)1341*3294Samaguire ra_routing_opt_set_unset_cb(raopt_t *raopt, scf_walkinfo_t *wip, boolean_t set)
1342*3294Samaguire {
1343*3294Samaguire scf_instance_t *inst = wip->inst;
1344*3294Samaguire scf_handle_t *h = scf_instance_handle(inst);
1345*3294Samaguire
1346*3294Samaguire return (ra_set_boolean_prop(h, inst, RA_PG_ROUTEADM,
1347*3294Samaguire raopt->opt_flags & RA_SVC_FLAG_IPV4_ROUTING ?
1348*3294Samaguire RA_PROP_IPV4_ROUTING_SET : RA_PROP_IPV6_ROUTING_SET,
1349*3294Samaguire B_FALSE, set));
1350*3294Samaguire }
1351*3294Samaguire
13523048Samaguire /*
13533048Samaguire * Shared function that either sets or determines persistent or current
13543048Samaguire * state. Setting persistent state (for next boot) involves setting
13553048Samaguire * the general_ovr/enabled value to the current service state, and
13563048Samaguire * the general/enabled value to the desired (next-boot) state.
13573048Samaguire * Setting current state involves removing the temporary state
13583048Samaguire * setting so the persistent state has effect.
13593048Samaguire *
13603048Samaguire * Persistent state is reported as being enabled if any of the
13613048Samaguire * candidate services have a general/enabled value set to true,
13623048Samaguire * while current state is reported as being enabled if any of the
13633048Samaguire * candidate services has a general_ovr/enabled or general/enabled
13643048Samaguire * value set to true.
13653048Samaguire */
13663048Samaguire static int
ra_get_set_opt_common_cb(raopt_t * raopt,scf_walkinfo_t * wip,boolean_t persistent,boolean_t get)13673048Samaguire ra_get_set_opt_common_cb(raopt_t *raopt, scf_walkinfo_t *wip,
13683048Samaguire boolean_t persistent, boolean_t get)
13693048Samaguire {
13703048Samaguire const char *inst_fmri = wip->fmri;
13713048Samaguire scf_instance_t *inst = wip->inst;
13723048Samaguire scf_handle_t *h = scf_instance_handle(inst);
13733048Samaguire scf_propertygroup_t *routeadm_pg;
13743048Samaguire boolean_t persistent_state_enabled;
13753048Samaguire boolean_t temporary_state_enabled;
13763048Samaguire boolean_t current_state_enabled;
13773048Samaguire boolean_t curr_svc = B_TRUE;
13783048Samaguire boolean_t found_proto;
13793048Samaguire char **protolist = NULL;
13803048Samaguire int i, ret, numvalues = 0;
13813048Samaguire
13823048Samaguire /*
13833048Samaguire * Ensure we are dealing with a routeadm-managed service. If
13843048Samaguire * the FMRI used for walking instances is NULL, it is reasonable
13853048Samaguire * that a service not have a routeadm property group as we will
13863048Samaguire * check all services in this case.
13873048Samaguire */
13883048Samaguire if (ra_get_pg(h, inst, RA_PG_ROUTEADM, B_TRUE, raopt->opt_fmri != NULL,
13893048Samaguire &routeadm_pg) == -1) {
13903048Samaguire /* Not a routing service, not an error. */
13913048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND &&
13923048Samaguire raopt->opt_fmri == NULL)
13933048Samaguire return (0);
13943048Samaguire return (-1);
13953048Samaguire }
13963048Samaguire scf_pg_destroy(routeadm_pg);
13973048Samaguire
13983048Samaguire /* Services with no "protocol" property are not routing daemons */
13993048Samaguire if (raopt->opt_fmri == NULL && ra_get_prop_as_string(h, inst,
14003048Samaguire RA_PG_ROUTEADM, RA_PROP_PROTO, B_TRUE, B_FALSE, NULL, &numvalues,
14013048Samaguire &protolist) == -1) {
14023048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND)
14033048Samaguire return (0);
14043048Samaguire return (-1);
14053048Samaguire }
14063048Samaguire
14073048Samaguire /*
14083048Samaguire * Skip invalid services based on flag settings. Flags are used when
14093048Samaguire * we run callback functions on all instances to identify
14103048Samaguire * the correct instances to operate on.
14113048Samaguire */
14123048Samaguire if (raopt->opt_flags & RA_SVC_FLAG_IPV4_ROUTING) {
14133048Samaguire found_proto = B_FALSE;
14143048Samaguire if (protolist != NULL) {
14153048Samaguire /* Check if protolist contains "ipv4" */
14163048Samaguire for (i = 0; i < numvalues; i++) {
14173048Samaguire if (protolist[i] != NULL && strcmp(
14183048Samaguire protolist[i], RA_PROPVAL_PROTO_IPV4) == 0)
14193048Samaguire found_proto = B_TRUE;
14203048Samaguire }
14213048Samaguire }
14223048Samaguire /* If not an ipv4 routing service, skip. */
14233048Samaguire if (protolist == NULL || !found_proto) {
14243048Samaguire ra_free_prop_values(numvalues, protolist);
14253048Samaguire return (0);
14263048Samaguire }
14273048Samaguire }
14283048Samaguire if (raopt->opt_flags & RA_SVC_FLAG_IPV6_ROUTING) {
14293048Samaguire found_proto = B_FALSE;
14303048Samaguire if (protolist != NULL) {
14313048Samaguire /* Check if protolist contains "ipv6" */
14323048Samaguire for (i = 0; i < numvalues; i++) {
14333048Samaguire if (protolist[i] != NULL && strcmp(
14343048Samaguire protolist[i], RA_PROPVAL_PROTO_IPV6) == 0)
14353048Samaguire found_proto = B_TRUE;
14363048Samaguire }
14373048Samaguire }
14383048Samaguire /* If not an ipv6 routing service, skip. */
14393048Samaguire if (protolist == NULL || !found_proto) {
14403048Samaguire ra_free_prop_values(numvalues, protolist);
14413048Samaguire return (0);
14423048Samaguire }
14433094Samaguire /*
14443094Samaguire * If no IPv6 interfaces are configured, do not apply
14453094Samaguire * the "enable" state change to this IPv6 routing service.
14463094Samaguire */
14473094Samaguire if (raopt->opt_enabled && ra_numv6intfs() < 1)
14483094Samaguire return (0);
14493048Samaguire }
14503048Samaguire ra_free_prop_values(numvalues, protolist);
14513048Samaguire
14523048Samaguire /* If enabling routing services, select only current routing services */
14533048Samaguire if (raopt->opt_fmri == NULL && !get && raopt->opt_enabled) {
14543048Samaguire if (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM,
14553048Samaguire RA_PROP_CURR_ROUTING_SVC, B_FALSE, B_FALSE,
14563048Samaguire &curr_svc) == -1)
14573048Samaguire return (0);
14583048Samaguire else if (!curr_svc && persistent) {
14593048Samaguire /*
14603048Samaguire * We apply "current" routing changes to all routing
14613048Samaguire * daemons, whether current or not, so bail if
14623048Samaguire * we are trying to make a persistent update to a
14633048Samaguire * non-"routing-svc".
14643048Samaguire */
14653048Samaguire return (0);
14663048Samaguire }
14673048Samaguire }
14683048Samaguire if (ra_get_boolean_prop(h, inst, SCF_PG_GENERAL, SCF_PROPERTY_ENABLED,
14693048Samaguire B_FALSE, B_TRUE, &persistent_state_enabled) == -1)
14703048Samaguire return (-1);
14713048Samaguire
14723048Samaguire current_state_enabled = persistent_state_enabled;
14733048Samaguire
14743048Samaguire if (ra_get_boolean_prop(h, inst, SCF_PG_GENERAL_OVR,
14753048Samaguire SCF_PROPERTY_ENABLED, B_FALSE, B_FALSE, &temporary_state_enabled)
14763048Samaguire == 0)
14773048Samaguire current_state_enabled = temporary_state_enabled;
14783048Samaguire
14793048Samaguire if (get) {
14803048Samaguire /*
14813048Samaguire * Persistent state is enabled if any services are
14823048Samaguire * persistently enabled, i.e. general/enabled == true).
14833048Samaguire * current state is enabled if any services
14843048Samaguire * services are currently enabled, i.e. if defined,
14853048Samaguire * general_ovr/enabled == true, if not, general/enabled == true.
14863048Samaguire */
14873048Samaguire if (persistent)
14883048Samaguire raopt->opt_enabled = raopt->opt_enabled ||
14893048Samaguire persistent_state_enabled;
14903048Samaguire else
14913048Samaguire raopt->opt_enabled = raopt->opt_enabled ||
14923048Samaguire current_state_enabled;
14933048Samaguire } else {
14943048Samaguire if (persistent) {
14953048Samaguire /*
14963048Samaguire * For peristent state changes, from -e/-d,
14973048Samaguire * we set the general_ovr/enabled value to the
14983048Samaguire * current state (to ensure it is preserved),
14993048Samaguire * while setting the general/enabled value to
15003048Samaguire * the desired value. This has the effect of
15013048Samaguire * the desired value coming into effect on next boot.
15023048Samaguire */
15033048Samaguire ret = current_state_enabled ?
15043048Samaguire smf_enable_instance(inst_fmri, SMF_TEMPORARY) :
15053048Samaguire smf_disable_instance(inst_fmri, SMF_TEMPORARY);
15063048Samaguire if (ret != 0) {
15073048Samaguire (void) fprintf(stderr, gettext(
15083048Samaguire "%s: unexpected libscf error: %s\n"),
15093048Samaguire myname, scf_strerror(scf_error()));
15103048Samaguire return (-1);
15113048Samaguire }
15123048Samaguire /*
15133048Samaguire * Refresh here so general_ovr/enabled state overrides
15143048Samaguire * general/enabled state.
15153048Samaguire */
15163048Samaguire (void) smf_refresh_instance(inst_fmri);
15173048Samaguire /*
15183048Samaguire * Now we can safely set the general/enabled value
15193048Samaguire * to the value we require on next boot (or
15203048Samaguire * "routeadm -u").
15213048Samaguire */
15223048Samaguire ret = ra_set_boolean_prop(h, inst, SCF_PG_GENERAL,
15233048Samaguire SCF_PROPERTY_ENABLED, B_FALSE, raopt->opt_enabled);
15243048Samaguire if (ret != 0)
15253048Samaguire return (-1);
15263048Samaguire /*
15273048Samaguire * Refresh here so general/enabled value is set.
15283048Samaguire */
15293048Samaguire (void) smf_refresh_instance(inst_fmri);
15303048Samaguire if (raopt->opt_fmri != NULL)
15313048Samaguire return (0);
15323048Samaguire (void) smf_refresh_instance(RA_INSTANCE_ROUTING_SETUP);
15333048Samaguire } else {
15343048Samaguire /*
15353157Samaguire * Refresh here to get latest property values prior
15363157Samaguire * to starting daemon.
15373157Samaguire */
15383157Samaguire (void) smf_refresh_instance(inst_fmri);
15393157Samaguire /*
15403048Samaguire * For current changes (result of -u), we
15413048Samaguire * enable/disable depending on persistent value
15423048Samaguire * stored in general/enabled. Here we disable
15433048Samaguire * old routing-svcs (identified by a current-routing-svc
15443048Samaguire * value of false) also.
15453048Samaguire */
15463048Samaguire ret = persistent_state_enabled && curr_svc ?
15473048Samaguire smf_enable_instance(inst_fmri, 0) :
15483048Samaguire smf_disable_instance(inst_fmri, 0);
15493048Samaguire if (ret != 0) {
15503048Samaguire (void) fprintf(stderr, gettext(
15513048Samaguire "%s: unexpected libscf error: %s\n"),
15523048Samaguire myname, scf_strerror(scf_error()));
15533048Samaguire return (-1);
15543048Samaguire }
15553157Samaguire if (current_state_enabled && persistent_state_enabled) {
15563157Samaguire /*
15573157Samaguire * Instance was already enabled, so we restart
15583157Samaguire * to get latest property values. This covers
15593157Samaguire * the case where users update properties
15603157Samaguire * via routeadm -m, and issue an update. The
15613157Samaguire * daemon should be running with the latest
15623157Samaguire * property values.
15633157Samaguire */
15643157Samaguire (void) smf_restart_instance(inst_fmri);
15653157Samaguire }
15663048Samaguire }
15673048Samaguire }
15683048Samaguire return (0);
15693048Samaguire }
15703048Samaguire
15713048Samaguire static int
ra_set_default_opt_cb(void * data,scf_walkinfo_t * wip)15723048Samaguire ra_set_default_opt_cb(void *data, scf_walkinfo_t *wip)
15733048Samaguire {
15743048Samaguire scf_instance_t *inst = wip->inst;
15753048Samaguire scf_handle_t *h = scf_instance_handle(inst);
15763048Samaguire raopt_t *raopt = data;
15773048Samaguire
15783048Samaguire return (ra_set_boolean_prop(h, inst, RA_PG_ROUTEADM,
15793048Samaguire raopt->opt_default_prop, B_FALSE, raopt->opt_default_enabled));
15803048Samaguire }
15813048Samaguire
15823048Samaguire static int
ra_get_default_opt_cb(void * data,scf_walkinfo_t * wip)15833048Samaguire ra_get_default_opt_cb(void *data, scf_walkinfo_t *wip)
15843048Samaguire {
15853048Samaguire scf_instance_t *inst = wip->inst;
15863048Samaguire scf_handle_t *h = scf_instance_handle(inst);
15873048Samaguire raopt_t *raopt = data;
15883048Samaguire
15893048Samaguire return (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM,
15903048Samaguire raopt->opt_default_prop, B_TRUE, B_TRUE,
15913048Samaguire &(raopt->opt_default_enabled)));
15923048Samaguire }
15933048Samaguire
15943048Samaguire /*
15953048Samaguire * Callbacks to set/retrieve persistent/default routing variable values.
15963048Samaguire * The set functions use the value stored in the var_value/var_default_value
15973048Samaguire * field of the associated ra_var_t, while the retrieval functions store
15983048Samaguire * the value retrieved in that field.
15993048Samaguire */
16003048Samaguire static int
ra_get_persistent_var_cb(void * data,scf_walkinfo_t * wip)16013048Samaguire ra_get_persistent_var_cb(void *data, scf_walkinfo_t *wip)
16023048Samaguire {
16033048Samaguire scf_instance_t *inst = wip->inst;
16043048Samaguire scf_handle_t *h = scf_instance_handle(inst);
16053048Samaguire ravar_t *ravar = data;
16063048Samaguire
16073048Samaguire return (ra_get_single_prop_as_string(h, inst, RA_PG_ROUTEADM,
16083048Samaguire ravar->var_prop, B_TRUE, B_TRUE, NULL, &ravar->var_value));
16093048Samaguire }
16103048Samaguire
16113048Samaguire static int
ra_set_persistent_var_cb(void * data,scf_walkinfo_t * wip)16123048Samaguire ra_set_persistent_var_cb(void *data, scf_walkinfo_t *wip)
16133048Samaguire {
16143048Samaguire scf_instance_t *inst = wip->inst;
16153048Samaguire scf_handle_t *h = scf_instance_handle(inst);
16163048Samaguire ravar_t *ravar = data;
16173048Samaguire
16183048Samaguire return (ra_set_prop_from_string(h, inst, RA_PG_ROUTEADM,
16193048Samaguire ravar->var_prop, SCF_TYPE_INVALID, B_FALSE, 1,
16203048Samaguire (const char **)&ravar->var_value));
16213048Samaguire }
16223048Samaguire
16233048Samaguire static int
ra_get_default_var_cb(void * data,scf_walkinfo_t * wip)16243048Samaguire ra_get_default_var_cb(void *data, scf_walkinfo_t *wip)
16253048Samaguire {
16263048Samaguire scf_instance_t *inst = wip->inst;
16273048Samaguire scf_handle_t *h = scf_instance_handle(inst);
16283048Samaguire ravar_t *ravar = data;
16293048Samaguire
16303048Samaguire return (ra_get_single_prop_as_string(h, inst, RA_PG_ROUTEADM,
16313048Samaguire ravar->var_default_prop, B_TRUE, B_TRUE, NULL,
16323048Samaguire &ravar->var_default_value));
16333048Samaguire }
16343048Samaguire
16353048Samaguire /*
16363048Samaguire * Depending on the value of the boolean_t * passed in, this callback
16373048Samaguire * either marks the relevant service(s) as current-routing-svcs (or unmarking)
16383048Samaguire * by setting that property to true or false. When routing services
16393048Samaguire * are to be enabled, the a current-routing-svc value of true flags the
16403048Samaguire * service as one to be enabled.
16413048Samaguire */
16423048Samaguire static int
ra_mark_routing_svcs_cb(void * data,scf_walkinfo_t * wip)16433048Samaguire ra_mark_routing_svcs_cb(void *data, scf_walkinfo_t *wip)
16443048Samaguire {
16453048Samaguire scf_instance_t *inst = wip->inst;
16463048Samaguire scf_handle_t *h = scf_instance_handle(inst);
16473048Samaguire boolean_t *mark = data;
16483048Samaguire boolean_t marked;
16493048Samaguire int numvalues = 0;
16503048Samaguire char **protolist = NULL;
16513048Samaguire
16523048Samaguire /* Check we are dealing with a routing daemon service */
16533048Samaguire if (ra_get_prop_as_string(h, inst, RA_PG_ROUTEADM, RA_PROP_PROTO,
16543048Samaguire B_TRUE, B_FALSE, NULL, &numvalues, &protolist) == -1)
16553048Samaguire return (0);
16563048Samaguire ra_free_prop_values(numvalues, protolist);
16573048Samaguire if (*mark)
16583048Samaguire return (ra_set_boolean_prop(h, inst, RA_PG_ROUTEADM,
16593048Samaguire RA_PROP_CURR_ROUTING_SVC, B_TRUE, B_TRUE));
16603048Samaguire /* Unmark service. */
16613048Samaguire if (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM,
16623048Samaguire RA_PROP_CURR_ROUTING_SVC, B_TRUE, B_FALSE, &marked) == 0 && marked)
16633048Samaguire return (ra_set_boolean_prop(h, inst, RA_PG_ROUTEADM,
16643048Samaguire RA_PROP_CURR_ROUTING_SVC, B_TRUE, B_FALSE));
16653048Samaguire return (0);
16663048Samaguire }
16673048Samaguire
16683048Samaguire /*
16693048Samaguire * List property values for all properties in the "routing" property
16703048Samaguire * group of the routing service instance.
16713048Samaguire */
16723048Samaguire
16733048Samaguire /* ARGSUSED0 */
16743048Samaguire static int
ra_list_props_cb(void * data,scf_walkinfo_t * wip)16753048Samaguire ra_list_props_cb(void *data, scf_walkinfo_t *wip)
16763048Samaguire {
16773048Samaguire const char *inst_fmri = wip->fmri;
16783048Samaguire scf_instance_t *inst = wip->inst;
16793048Samaguire scf_handle_t *h = scf_instance_handle(inst);
16803048Samaguire scf_iter_t *propiter, *valiter;
16813048Samaguire scf_propertygroup_t *pg;
16823048Samaguire scf_property_t *prop;
16833048Samaguire scf_value_t *val;
16843048Samaguire char **protolist = NULL, *pnamebuf, *valbuf;
16853048Samaguire ssize_t pnamelen, vallen;
16863048Samaguire int numvalues = 0;
16873048Samaguire int propiterret, valiterret, retval = 0;
16883048Samaguire
16893048Samaguire /* Services with no "protocol" property are not routing daemons */
16903048Samaguire if (ra_get_prop_as_string(h, inst, RA_PG_ROUTEADM, RA_PROP_PROTO,
16913048Samaguire B_TRUE, B_FALSE, NULL, &numvalues, &protolist) == -1) {
16923048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND)
16933048Samaguire (void) fprintf(stderr,
16943048Samaguire gettext("%s: %s is not a routing daemon service\n"),
16953048Samaguire myname, inst_fmri);
16963048Samaguire else
16973048Samaguire (void) fprintf(stderr,
16983048Samaguire gettext("%s: unexpected libscf error: %s\n"),
16993048Samaguire myname, scf_strerror(scf_error()));
17003048Samaguire ra_free_prop_values(numvalues, protolist);
17013048Samaguire return (-1);
17023048Samaguire }
17033048Samaguire ra_free_prop_values(numvalues, protolist);
17043048Samaguire
17053048Samaguire if (ra_get_pg(h, inst, RA_PG_ROUTING, B_TRUE, B_FALSE, &pg) == -1) {
17063048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) {
17073048Samaguire (void) printf("%s: no %s property group for %s\n",
17083048Samaguire myname, RA_PG_ROUTING, inst_fmri);
17093048Samaguire return (0);
17103048Samaguire }
17113048Samaguire (void) fprintf(stderr,
17123048Samaguire gettext("%s: unexpected libscf error: %s\n"),
17133048Samaguire myname, scf_strerror(scf_error()));
17143048Samaguire return (-1);
17153048Samaguire }
17163048Samaguire
17173048Samaguire (void) printf("%s:\n", inst_fmri);
17183048Samaguire
17193048Samaguire /* Create an iterator to walk through all properties */
17203048Samaguire if ((propiter = scf_iter_create(h)) == NULL ||
17213048Samaguire (prop = scf_property_create(h)) == NULL ||
17223048Samaguire scf_iter_pg_properties(propiter, pg) != 0) {
17233048Samaguire (void) fprintf(stderr, gettext
17243048Samaguire ("%s: could not iterate through properties for %s: %s\n"),
17253048Samaguire myname, inst_fmri, scf_strerror(scf_error()));
17263048Samaguire }
17273048Samaguire while ((propiterret = scf_iter_next_property(propiter, prop)) == 1) {
17283048Samaguire if ((pnamelen = scf_property_get_name(prop, NULL, 0) + 1)
17293048Samaguire == 0) {
17303048Samaguire (void) fprintf(stderr, gettext("%s: could not retrieve "
17313048Samaguire "property name for instance %s: %s\n"), myname,
17323048Samaguire inst_fmri, scf_strerror(scf_error()));
17333048Samaguire retval = -1;
17343048Samaguire break;
17353048Samaguire }
17363048Samaguire if ((pnamebuf = malloc(pnamelen)) == NULL) {
17373048Samaguire (void) fprintf(stderr,
17383048Samaguire gettext("%s: out of memory\n"), myname);
17393048Samaguire retval = -1;
17403048Samaguire break;
17413048Samaguire }
17423048Samaguire (void) scf_property_get_name(prop, pnamebuf,
17433048Samaguire pnamelen);
17443048Samaguire (void) printf("\t%s = ", pnamebuf);
17453048Samaguire if ((valiter = scf_iter_create(h)) == NULL ||
17463048Samaguire (val = scf_value_create(h)) == NULL ||
17473048Samaguire scf_iter_property_values(valiter, prop)
17483048Samaguire != 0) {
17493048Samaguire (void) fprintf(stderr, gettext
17503048Samaguire ("%s: could not iterate through "
17513048Samaguire "properties for %s: %s\n"), myname, inst_fmri,
17523048Samaguire scf_strerror(scf_error()));
17533048Samaguire scf_value_destroy(val);
17543048Samaguire scf_iter_destroy(valiter);
17553048Samaguire free(pnamebuf);
17563048Samaguire retval = -1;
17573048Samaguire break;
17583048Samaguire }
17593048Samaguire while ((valiterret = scf_iter_next_value(valiter, val)) == 1) {
17603048Samaguire if ((vallen = scf_value_get_as_string
17613048Samaguire (val, NULL, 0) + 1) == 0) {
17623048Samaguire (void) fprintf(stderr, gettext
17633048Samaguire ("%s: could not retrieve "
17643048Samaguire "property value for instance %s, "
17653048Samaguire "property %s: %s\n"), myname, inst_fmri,
17663048Samaguire pnamebuf, scf_strerror(scf_error()));
17673048Samaguire retval = -1;
17683048Samaguire } else if ((valbuf = malloc(vallen)) == NULL) {
17693048Samaguire (void) fprintf(stderr,
17703048Samaguire gettext("%s: out of memory\n"), myname);
17713048Samaguire retval = -1;
17723048Samaguire }
17733048Samaguire if (retval == -1) {
17743048Samaguire scf_iter_destroy(valiter);
17753048Samaguire scf_value_destroy(val);
17763048Samaguire free(pnamebuf);
17773048Samaguire goto out;
17783048Samaguire }
17793048Samaguire (void) scf_value_get_as_string(val, valbuf, vallen);
17803048Samaguire (void) printf("%s ", valbuf);
17813048Samaguire free(valbuf);
17823048Samaguire }
17833048Samaguire (void) printf("\n");
17843048Samaguire scf_iter_destroy(valiter);
17853048Samaguire scf_value_destroy(val);
17863048Samaguire free(pnamebuf);
17873048Samaguire if (valiterret == -1) {
17883048Samaguire (void) fprintf(stderr,
17893048Samaguire gettext("%s: could not iterate through"
17903048Samaguire "properties for %s: %s\n"), myname, inst_fmri,
17913048Samaguire scf_strerror(scf_error()));
17923048Samaguire retval = -1;
17933048Samaguire break;
17943048Samaguire }
17953048Samaguire }
17963048Samaguire out:
17973048Samaguire scf_iter_destroy(propiter);
17983048Samaguire scf_property_destroy(prop);
17993048Samaguire scf_pg_destroy(pg);
18003048Samaguire if (propiterret == -1)
18013048Samaguire (void) fprintf(stderr, gettext
18023048Samaguire ("%s: could not iterate through properties for %s: %s\n"),
18033048Samaguire myname, inst_fmri, scf_strerror(scf_error()));
18043048Samaguire return (retval);
18053048Samaguire }
18063048Samaguire
18073048Samaguire /*
18083048Samaguire * Modify property with name stored in passed-in ra_prop_t to have
18093048Samaguire * the assocatied values. Only works for existing properties in
18103048Samaguire * the "routing" property group for routing daemon services, so all
18113048Samaguire * routing daemons should place configurable options in that group.
18123048Samaguire */
18133048Samaguire static int
ra_modify_props_cb(void * data,scf_walkinfo_t * wip)18143048Samaguire ra_modify_props_cb(void *data, scf_walkinfo_t *wip)
18153048Samaguire {
18163048Samaguire const char *inst_fmri = wip->fmri;
18173048Samaguire scf_instance_t *inst = wip->inst;
18183048Samaguire scf_handle_t *h = scf_instance_handle(inst);
18193048Samaguire ra_prop_t *raprop = data;
18203048Samaguire int numvalues = 0;
18213048Samaguire char **protolist = NULL;
18223048Samaguire
18233048Samaguire /* Services with no "protocol" property are not routing daemons */
18243048Samaguire if (ra_get_prop_as_string(h, inst, RA_PG_ROUTEADM, RA_PROP_PROTO,
18253048Samaguire B_TRUE, B_FALSE, NULL, &numvalues, &protolist) == -1) {
18263048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND)
18273048Samaguire (void) fprintf(stderr,
18283048Samaguire gettext("%s: %s is not a routing daemon service\n"),
18293048Samaguire myname, inst_fmri);
18303048Samaguire else
18313048Samaguire (void) fprintf(stderr,
18323048Samaguire gettext("%s: unexpected libscf error: %s\n"),
18333048Samaguire myname, scf_strerror(scf_error()));
18343048Samaguire ra_free_prop_values(numvalues, protolist);
18353048Samaguire return (-1);
18363048Samaguire }
18373048Samaguire ra_free_prop_values(numvalues, protolist);
18383048Samaguire
18393048Samaguire if (ra_set_prop_from_string(h, inst, RA_PG_ROUTING, raprop->prop_name,
18403048Samaguire SCF_TYPE_INVALID, B_FALSE, raprop->prop_numvalues,
18413048Samaguire (const char **)raprop->prop_values) == -1)
18423048Samaguire return (-1);
18433048Samaguire
18443048Samaguire (void) smf_refresh_instance(inst_fmri);
18453048Samaguire return (0);
18463048Samaguire }
18473048Samaguire
18483048Samaguire /*
18493048Samaguire * Display FMRI, state for each routing daemon service.
18503048Samaguire */
18513048Samaguire
18523048Samaguire /* ARGSUSED0 */
18533048Samaguire static int
ra_print_state_cb(void * data,scf_walkinfo_t * wip)18543048Samaguire ra_print_state_cb(void *data, scf_walkinfo_t *wip)
18553048Samaguire {
18563048Samaguire const char *inst_fmri = wip->fmri;
18573048Samaguire scf_instance_t *inst = wip->inst;
18583048Samaguire scf_handle_t *h = scf_instance_handle(inst);
18593048Samaguire char *inst_state, **protolist = NULL;
18603048Samaguire int numvalues = 0;
18613048Samaguire
18623048Samaguire /* Ensure service is a routing daemon */
18633048Samaguire if (ra_get_prop_as_string(h, inst, RA_PG_ROUTEADM, RA_PROP_PROTO,
18643048Samaguire B_TRUE, B_FALSE, NULL, &numvalues, &protolist) == -1)
18653048Samaguire return (0);
18663048Samaguire ra_free_prop_values(numvalues, protolist);
18673048Samaguire
18683048Samaguire if ((inst_state = smf_get_state(inst_fmri)) == NULL) {
18693048Samaguire (void) fprintf(stderr,
18703048Samaguire gettext("%s: could not retrieve state for %s: %s\n"),
18713048Samaguire myname, inst_fmri, scf_strerror(scf_error()));
18723048Samaguire return (-1);
18733048Samaguire }
18743048Samaguire (void) printf("%27s %2s\n", inst_state, inst_fmri);
18753048Samaguire free(inst_state);
18763048Samaguire
18773048Samaguire return (0);
18783048Samaguire }
18793048Samaguire
18803048Samaguire static int
ra_get_pg(scf_handle_t * h,scf_instance_t * inst,const char * pgname,boolean_t composed,boolean_t required,scf_propertygroup_t ** pg)18813048Samaguire ra_get_pg(scf_handle_t *h, scf_instance_t *inst, const char *pgname,
18823048Samaguire boolean_t composed, boolean_t required, scf_propertygroup_t **pg)
18833048Samaguire {
18843048Samaguire /* Retrieve (possibly composed) property group for instance */
18853048Samaguire if ((*pg = scf_pg_create(h)) == NULL || (composed &&
18863048Samaguire scf_instance_get_pg_composed(inst, NULL, pgname, *pg) != 0) ||
18873048Samaguire (!composed && scf_instance_get_pg(inst, pgname, *pg) != 0)) {
18883048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) {
18893048Samaguire if (required)
18903048Samaguire (void) fprintf(stderr, gettext(
18913048Samaguire "%s: no such property group %s\n"),
18923048Samaguire myname, pgname);
18933048Samaguire return (-1);
18943048Samaguire }
18953048Samaguire if (required)
18963048Samaguire (void) fprintf(stderr, gettext(
18973048Samaguire "%s: unexpected libscf error: %s\n"), myname,
18983048Samaguire scf_strerror(scf_error()));
18993048Samaguire return (-1);
19003048Samaguire }
19013048Samaguire return (0);
19023048Samaguire }
19033048Samaguire
19043048Samaguire static int
ra_get_boolean_prop(scf_handle_t * h,scf_instance_t * inst,const char * pgname,const char * propname,boolean_t composed,boolean_t required,boolean_t * val)19053048Samaguire ra_get_boolean_prop(scf_handle_t *h, scf_instance_t *inst,
19063048Samaguire const char *pgname, const char *propname, boolean_t composed,
19073048Samaguire boolean_t required, boolean_t *val)
19083048Samaguire {
19093048Samaguire char *valstr;
19103048Samaguire
19113048Samaguire if (ra_get_single_prop_as_string(h, inst, pgname, propname,
19123048Samaguire composed, required, NULL, &valstr) != 0)
19133048Samaguire return (-1);
19143048Samaguire *val = strcmp(valstr, RA_PROPVAL_BOOLEAN_TRUE) == 0;
19153048Samaguire free(valstr);
19163048Samaguire return (0);
19173048Samaguire }
19183048Samaguire
19193048Samaguire static int
ra_get_single_prop_as_string(scf_handle_t * h,scf_instance_t * inst,const char * pgname,const char * propname,boolean_t composed,boolean_t required,scf_type_t * type,char ** value)19203048Samaguire ra_get_single_prop_as_string(scf_handle_t *h, scf_instance_t *inst,
19213048Samaguire const char *pgname, const char *propname, boolean_t composed,
19223048Samaguire boolean_t required, scf_type_t *type, char **value)
19233048Samaguire {
19243048Samaguire char **values;
19253048Samaguire int numvalues = 1;
19263048Samaguire
19273048Samaguire if (ra_get_prop_as_string(h, inst, pgname, propname, composed, required,
19283048Samaguire type, &numvalues, &values) == -1)
19293048Samaguire return (-1);
19303048Samaguire *value = values[0];
19313048Samaguire free(values);
19323048Samaguire return (0);
19333048Samaguire }
19343048Samaguire
19353048Samaguire /*
19363048Samaguire * Retrieve property named in propname, possibly using the composed
19373048Samaguire * property group view (union of instance and service-level properties,
19383048Samaguire * where instance-level properties override service-level values).
19393048Samaguire */
19403048Samaguire static int
ra_get_prop_as_string(scf_handle_t * h,scf_instance_t * inst,const char * pgname,const char * propname,boolean_t composed,boolean_t required,scf_type_t * type,int * numvalues,char *** values)19413048Samaguire ra_get_prop_as_string(scf_handle_t *h, scf_instance_t *inst,
19423048Samaguire const char *pgname, const char *propname, boolean_t composed,
19433048Samaguire boolean_t required, scf_type_t *type, int *numvalues, char ***values)
19443048Samaguire {
19453048Samaguire scf_propertygroup_t *pg = NULL;
19463048Samaguire scf_property_t *prop = NULL;
19473048Samaguire scf_iter_t *valiter = NULL;
19483048Samaguire scf_value_t *val = NULL;
19493048Samaguire ssize_t vallen = 0;
19503048Samaguire int valiterret, i, numvalues_retrieved, ret = 0;
19513048Samaguire
19523048Samaguire if (ra_get_pg(h, inst, pgname, composed, required, &pg) == -1)
19533048Samaguire return (-1);
19543048Samaguire
19553048Samaguire *values = NULL;
19563048Samaguire /*
19573048Samaguire * Retrieve values. All values routeadm needs to retrieve
19583048Samaguire * (bar those gathered by routeadm -l), are known to be single-valued.
19593048Samaguire */
19603048Samaguire if ((prop = scf_property_create(h)) == NULL)
19613048Samaguire goto error;
19623048Samaguire if (scf_pg_get_property(pg, propname, prop) != 0) {
19633048Samaguire *numvalues = 0;
19643048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) {
19653048Samaguire if (required)
19663048Samaguire (void) fprintf(stderr, gettext(
19673048Samaguire "%s: property %s/%s not found\n"),
19683048Samaguire myname, pgname, propname);
19693048Samaguire ret = -1;
19703048Samaguire goto out;
19713048Samaguire }
19723048Samaguire goto error;
19733048Samaguire }
19743048Samaguire if ((val = scf_value_create(h)) == NULL &&
19753048Samaguire scf_property_get_value(prop, val) != 0 ||
19763048Samaguire (valiter = scf_iter_create(h)) == NULL ||
19773048Samaguire scf_iter_property_values(valiter, prop) != 0)
19783048Samaguire goto error;
19793048Samaguire /* retrieve each value */
19803048Samaguire for (numvalues_retrieved = 0;
19813048Samaguire (valiterret = scf_iter_next_value(valiter, val)) == 1;
19823048Samaguire numvalues_retrieved++) {
19833048Samaguire if ((vallen = scf_value_get_as_string
19843048Samaguire (val, NULL, 0) + 1) == 0)
19853048Samaguire goto error;
19863048Samaguire if ((*values = realloc(*values,
19873048Samaguire sizeof (*values) + sizeof (char *))) == NULL ||
19883048Samaguire ((*values)[numvalues_retrieved] = malloc(vallen)) == NULL) {
19893048Samaguire (void) fprintf(stderr, gettext(
19903048Samaguire "%s: out of memory\n"), myname);
19913048Samaguire ret = -1;
19923048Samaguire goto out;
19933048Samaguire }
19943048Samaguire (void) scf_value_get_as_string(val,
19953048Samaguire (*values)[numvalues_retrieved], vallen);
19963048Samaguire }
19973048Samaguire if (valiterret == -1)
19983048Samaguire goto error;
19993048Samaguire /*
20003048Samaguire * if *numvalues != 0, it holds expected number of values. If a
20013048Samaguire * different number are found, it is an error.
20023048Samaguire */
20033048Samaguire if (*numvalues != 0 && *numvalues != numvalues_retrieved) {
20043048Samaguire (void) fprintf(stderr, gettext(
20053048Samaguire "%s: got %d values for property %s/%s, expected %d\n"),
20063048Samaguire myname, numvalues_retrieved, pgname, propname, *numvalues);
20073048Samaguire ret = -1;
20083048Samaguire goto out;
20093048Samaguire }
20103048Samaguire *numvalues = numvalues_retrieved;
20113048Samaguire
20123048Samaguire /* Retrieve property type if required. */
20133048Samaguire if (type != NULL)
20143048Samaguire (void) scf_property_type(prop, type);
20153048Samaguire
20163048Samaguire goto out;
20173048Samaguire error:
20183048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) {
20193048Samaguire (void) fprintf(stderr, gettext(
20203048Samaguire "%s: property %s not found"), myname, propname);
20213048Samaguire } else {
20223048Samaguire (void) fprintf(stderr, gettext(
20233048Samaguire "%s: unexpected libscf error: %s, "), myname);
20243048Samaguire }
20253048Samaguire for (i = 0; i < numvalues_retrieved; i++)
20263048Samaguire free((*values)[i]);
20273048Samaguire if (*values != NULL)
20283048Samaguire free(*values);
20293048Samaguire
20303048Samaguire ret = -1;
20313048Samaguire out:
20323048Samaguire if (val != NULL)
20333048Samaguire scf_value_destroy(val);
20343048Samaguire if (valiter != NULL)
20353048Samaguire scf_iter_destroy(valiter);
20363048Samaguire if (prop != NULL)
20373048Samaguire scf_property_destroy(prop);
20383048Samaguire if (pg != NULL)
20393048Samaguire scf_pg_destroy(pg);
20403048Samaguire return (ret);
20413048Samaguire }
20423048Samaguire
20433048Samaguire static void
ra_free_prop_values(int numvalues,char ** values)20443048Samaguire ra_free_prop_values(int numvalues, char **values)
20453048Samaguire {
20463048Samaguire int i;
20473048Samaguire if (values != NULL) {
20483048Samaguire for (i = 0; i < numvalues; i++)
20493048Samaguire free(values[i]);
20503048Samaguire free(values);
20513048Samaguire }
20523048Samaguire }
20533048Samaguire
20543048Samaguire static int
ra_set_boolean_prop(scf_handle_t * h,scf_instance_t * inst,const char * pgname,const char * prop,boolean_t create,boolean_t propval)20553048Samaguire ra_set_boolean_prop(scf_handle_t *h, scf_instance_t *inst, const char *pgname,
20563048Samaguire const char *prop, boolean_t create, boolean_t propval)
20573048Samaguire {
20583048Samaguire const char *val = propval ? RA_PROPVAL_BOOLEAN_TRUE :
20593048Samaguire RA_PROPVAL_BOOLEAN_FALSE;
20603048Samaguire
20613048Samaguire return (ra_set_prop_from_string(h, inst, pgname, prop, SCF_TYPE_BOOLEAN,
20623048Samaguire create, 1, &val));
20633048Samaguire }
20643048Samaguire
20653048Samaguire /*
20663048Samaguire * Set the property named in propname to the values passed in in the propvals
20673048Samaguire * array. Only create a new property if "create" is true.
20683048Samaguire */
20693048Samaguire static int
ra_set_prop_from_string(scf_handle_t * h,scf_instance_t * inst,const char * pgname,const char * propname,scf_type_t proptype,boolean_t create,int numpropvals,const char ** propvals)20703048Samaguire ra_set_prop_from_string(scf_handle_t *h, scf_instance_t *inst,
20713048Samaguire const char *pgname, const char *propname, scf_type_t proptype,
20723048Samaguire boolean_t create, int numpropvals, const char **propvals)
20733048Samaguire {
20743048Samaguire scf_propertygroup_t *instpg = NULL, *cpg = NULL;
20753048Samaguire scf_type_t oldproptype, newproptype = proptype;
20763048Samaguire scf_property_t *prop = NULL;
20773048Samaguire scf_value_t **values = NULL;
20783048Samaguire scf_transaction_t *tx = NULL;
20793048Samaguire scf_transaction_entry_t *ent = NULL;
20803048Samaguire boolean_t new = B_FALSE;
20813048Samaguire int i, retval, numvalues = 0, ret = 0;
20823048Samaguire char *pgtype = NULL, **ovalues;
20833048Samaguire ssize_t typelen;
20843048Samaguire
20853048Samaguire /* Firstly, does property exist? If not, and create is false, bail */
20863048Samaguire if (ra_get_prop_as_string(h, inst, pgname, propname, B_TRUE,
20873048Samaguire B_FALSE, &oldproptype, &numvalues, &ovalues) == -1) {
20883048Samaguire if (scf_error() != SCF_ERROR_NOT_FOUND)
20893048Samaguire goto error;
20903048Samaguire if (!create) {
20913048Samaguire (void) fprintf(stderr, gettext(
20923048Samaguire "%s: no such property %s/%s\n"), myname, pgname,
20933048Samaguire propname);
20943048Samaguire return (-1);
20953048Samaguire }
20963048Samaguire } else
20973048Samaguire ra_free_prop_values(numvalues, ovalues);
20983048Samaguire
20993048Samaguire /* Use old property type */
21003048Samaguire if (proptype == SCF_TYPE_INVALID)
21013048Samaguire newproptype = oldproptype;
21023048Samaguire
21033048Samaguire /*
21043048Samaguire * Does property group exist at instance level? If not, we need to
21053048Samaguire * create it, since the composed view of the property group did
21063048Samaguire * contain the property. We never modify properties at the service
21073048Samaguire * level, as it`s possible that multiple instances will inherit those
21083048Samaguire * settings.
21093048Samaguire */
21103048Samaguire if (ra_get_pg(h, inst, pgname, B_FALSE, B_FALSE, &instpg) == -1) {
21113048Samaguire if (scf_error() != SCF_ERROR_NOT_FOUND)
21123048Samaguire goto error;
21133048Samaguire /* Ensure pg exists at service level, get composed pg */
21143048Samaguire if (ra_get_pg(h, inst, pgname, B_TRUE, B_FALSE, &cpg) == -1)
21153048Samaguire goto error;
21163048Samaguire
21173048Samaguire /* Create instance-level property group */
21183048Samaguire if ((typelen = scf_pg_get_type(cpg, NULL, 0) + 1) == 0)
21193048Samaguire goto error;
21203048Samaguire if ((pgtype = malloc(typelen)) == NULL) {
21213048Samaguire (void) fprintf(stderr, gettext(
21223048Samaguire "%s: out of memory\n"), myname);
21233048Samaguire goto error;
21243048Samaguire }
21253048Samaguire (void) scf_pg_get_type(cpg, pgtype, typelen);
21263048Samaguire if ((instpg = scf_pg_create(h)) == NULL ||
21273048Samaguire scf_instance_add_pg(inst, pgname, pgtype, 0, instpg)
21283048Samaguire == -1) {
21293048Samaguire (void) fprintf(stderr, gettext(
21303048Samaguire "%s: could not create property group %s\n"),
21313048Samaguire myname, pgname);
21323048Samaguire goto error;
21333048Samaguire }
21343048Samaguire }
21353048Samaguire if ((prop = scf_property_create(h)) == NULL)
21363048Samaguire goto error;
21373048Samaguire if ((values = calloc(numpropvals, sizeof (scf_value_t *))) == NULL) {
21383048Samaguire (void) fprintf(stderr, gettext("%s: out of memory"), myname);
21393048Samaguire goto error;
21403048Samaguire }
21413048Samaguire if (scf_pg_get_property(instpg, propname, prop) != 0) {
21423048Samaguire /* New property? */
21433048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND)
21443048Samaguire new = B_TRUE;
21453048Samaguire else
21463048Samaguire goto error;
21473048Samaguire }
21483048Samaguire if ((tx = scf_transaction_create(h)) == NULL ||
21493048Samaguire (ent = scf_entry_create(h)) == NULL)
21503048Samaguire goto error;
21513048Samaguire retry:
21523048Samaguire if (scf_transaction_start(tx, instpg) == -1)
21533048Samaguire goto error;
21543048Samaguire if (new) {
21553048Samaguire if (scf_transaction_property_new(tx, ent, propname,
21563048Samaguire newproptype) == -1)
21573048Samaguire goto error;
21583048Samaguire } else if (scf_transaction_property_change(tx, ent, propname,
21593048Samaguire newproptype) == -1)
21603048Samaguire goto error;
21613048Samaguire for (i = 0; i < numpropvals; i++) {
21623048Samaguire if ((values[i] = scf_value_create(h)) == NULL ||
21633048Samaguire scf_value_set_from_string(values[i], newproptype,
21643048Samaguire propvals[i] == NULL ? "": propvals[i]) == -1 ||
21653048Samaguire scf_entry_add_value(ent, values[i]) != 0)
21663048Samaguire goto error;
21673048Samaguire }
21683048Samaguire retval = scf_transaction_commit(tx);
21693048Samaguire if (retval == 0) {
21703048Samaguire scf_transaction_reset(tx);
21713048Samaguire if (scf_pg_update(instpg) == -1)
21723048Samaguire goto error;
21733048Samaguire goto retry;
21743048Samaguire }
21753048Samaguire if (retval == -1)
21763048Samaguire goto error;
21773048Samaguire goto out;
21783048Samaguire error:
21793048Samaguire switch (scf_error()) {
21803048Samaguire case SCF_ERROR_INVALID_ARGUMENT:
21813048Samaguire (void) fprintf(stderr, gettext(
21823048Samaguire "%s: invalid value for property %s/%s\n"), myname,
21833048Samaguire pgname, propname);
21843048Samaguire break;
21853048Samaguire case SCF_ERROR_NOT_FOUND:
21863048Samaguire (void) fprintf(stderr, gettext(
21873048Samaguire "%s: no such property %s/%s\n"), myname,
21883048Samaguire pgname, propname);
21893048Samaguire break;
21903048Samaguire default:
21913048Samaguire (void) fprintf(stderr, gettext(
21923048Samaguire "%s: unexpected libscf error: %s\n"), myname,
21933048Samaguire scf_strerror(scf_error()));
21943048Samaguire break;
21953048Samaguire }
21963048Samaguire ret = -1;
21973048Samaguire out:
21983048Samaguire if (tx != NULL)
21993048Samaguire scf_transaction_destroy(tx);
22003048Samaguire if (ent != NULL)
22013048Samaguire scf_entry_destroy(ent);
22023048Samaguire if (values != NULL) {
22033048Samaguire for (i = 0; i < numpropvals; i++) {
22043048Samaguire if (values[i] != NULL)
22053048Samaguire scf_value_destroy(values[i]);
22063048Samaguire }
22073048Samaguire free(values);
22083048Samaguire }
22093048Samaguire if (prop != NULL)
22103048Samaguire scf_property_destroy(prop);
22113048Samaguire if (cpg != NULL)
22123048Samaguire scf_pg_destroy(cpg);
22133048Samaguire if (instpg != NULL)
22143048Samaguire scf_pg_destroy(instpg);
22153048Samaguire if (pgtype != NULL)
22163048Samaguire free(pgtype);
22173048Samaguire return (ret);
22183048Samaguire }
22193048Samaguire
22203048Samaguire /*
22213048Samaguire * This function gathers configuration from the legacy /etc/inet/routing.conf,
22223048Samaguire * if any, and sets the appropriate variable values accordingly. Once
22233048Samaguire * these are set, the legacy daemons are checked to see if they have
22243048Samaguire * SMF counterparts (ra_check_legacy_daemons()). If they do, the
22253048Samaguire * configuration is upgraded. Finally, the legacy option settings are
22263048Samaguire * applied, enabling/disabling the routing/forwarding services as
22273048Samaguire * appropriate.
22283048Samaguire */
22293048Samaguire static int
ra_upgrade_from_legacy_conf(void)22303048Samaguire ra_upgrade_from_legacy_conf(void)
22313048Samaguire {
22323048Samaguire scf_handle_t *h = NULL;
22333048Samaguire scf_instance_t *inst = NULL;
22343048Samaguire int ret = 0, i, r;
22353048Samaguire boolean_t old_conf_read;
22363048Samaguire ravar_t *routing_svcs = ra_str2var(RA_VAR_ROUTING_SVCS);
22373048Samaguire
22383048Samaguire /*
22393048Samaguire * First, determine if we have already upgraded - if "routing-conf-read"
22403048Samaguire * is true, we bail. The use of a boolean property indicating if
22413048Samaguire * routing.conf has been read and applied might seem a lot more
22423048Samaguire * work than simply copying routing.conf aside, but leaving the
22433048Samaguire * file in place allows users to downgrade and have their old
22443048Samaguire * routing configuration still in place.
22453048Samaguire */
22463048Samaguire if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
22473048Samaguire scf_handle_bind(h) == -1) {
22483048Samaguire (void) fprintf(stderr, gettext(
22493048Samaguire "%s: cannot connect to SMF repository\n"), myname);
22503048Samaguire ret = -1;
22513048Samaguire goto out;
22523048Samaguire }
22533048Samaguire if ((inst = scf_instance_create(h)) == NULL ||
22543048Samaguire scf_handle_decode_fmri(h, RA_INSTANCE_ROUTING_SETUP,
22553048Samaguire NULL, NULL, inst, NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) {
22563048Samaguire (void) fprintf(stderr, gettext(
22573048Samaguire "%s: unexpected libscf error: %s\n"), myname,
22583048Samaguire scf_strerror(scf_error()));
22593048Samaguire ret = -1;
22603048Samaguire goto out;
22613048Samaguire }
22623048Samaguire if (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM,
22633048Samaguire RA_PROP_ROUTING_CONF_READ, B_TRUE, B_TRUE, &old_conf_read) == -1) {
22643048Samaguire ret = -1;
22653048Samaguire goto out;
22663048Samaguire }
22673048Samaguire
22683048Samaguire if (old_conf_read)
22693048Samaguire goto out;
22703048Samaguire
22713048Samaguire /*
22723048Samaguire * Now set "routing-conf-read" to true so we don`t reimport legacy
22733048Samaguire * configuration again.
22743048Samaguire */
22753048Samaguire if (ra_set_boolean_prop(h, inst, RA_PG_ROUTEADM,
22763048Samaguire RA_PROP_ROUTING_CONF_READ, B_FALSE, B_TRUE) == -1)
22773048Samaguire return (-1);
22783048Samaguire (void) smf_refresh_instance(RA_INSTANCE_ROUTING_SETUP);
22793048Samaguire
22803048Samaguire ra_resetvars(NULL);
22813048Samaguire
22823048Samaguire /* First, gather values from routing.conf */
22833048Samaguire if ((r = ra_parseconf()) == -1) {
22843048Samaguire ret = -1;
22853048Samaguire goto out;
22863048Samaguire }
22873048Samaguire /* No routing.conf file found */
22883048Samaguire if (r == 0)
22893048Samaguire goto out;
22903048Samaguire /*
22913048Samaguire * Now, set the options/variables gathered. We set variables first,
22923048Samaguire * as we cannot enable routing before we determine the daemons
22933048Samaguire * to enable.
22943048Samaguire */
22953048Samaguire
22963048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) {
22973048Samaguire /* Skip routing-svcs var, not featured in legacy config */
22983048Samaguire if (strcmp(ra_vars[i].var_name, RA_VAR_ROUTING_SVCS) == 0)
22993048Samaguire continue;
23003048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb, ra_vars[i].var_fmri,
23013048Samaguire &(ra_vars[i])) == -1) {
23023048Samaguire ret = -1;
23033048Samaguire goto out;
23043048Samaguire }
23053048Samaguire }
23063048Samaguire /* Clear routing-svcs value */
23073048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb, routing_svcs->var_fmri,
23083048Samaguire routing_svcs) == -1) {
23093048Samaguire ret = -1;
23103048Samaguire goto out;
23113048Samaguire }
23123048Samaguire
23133048Samaguire if (ra_check_legacy_daemons() == -1) {
23143048Samaguire ret = -1;
23153048Samaguire goto out;
23163048Samaguire }
23173048Samaguire
23183048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) {
23193048Samaguire if (ra_smf_cb(ra_set_persistent_opt_cb, ra_opts[i].opt_fmri,
23203048Samaguire &(ra_opts[i])) == -1 ||
23213048Samaguire ra_smf_cb(ra_set_default_opt_cb,
23223048Samaguire ra_opts[i].opt_default_fmri, &(ra_opts[i])) == -1) {
23233048Samaguire ret = -1;
23243048Samaguire break;
23253048Samaguire }
23263048Samaguire }
23273048Samaguire out:
23283048Samaguire if (inst != NULL)
23293048Samaguire scf_instance_destroy(inst);
23303048Samaguire if (h != NULL)
23313048Samaguire scf_handle_destroy(h);
23323048Samaguire
23333048Samaguire return (ret);
23343048Samaguire }
23353048Samaguire
23363048Samaguire /*
23373094Samaguire *
23383094Samaguire * Return the number of IPv6 addresses configured. This answers the
23393094Samaguire * generic question, "is IPv6 configured?". We only start in.ndpd if IPv6
23403094Samaguire * is configured, and we also only enable IPv6 routing daemons if IPv6 is
23413094Samaguire * enabled.
23423094Samaguire */
23433094Samaguire static int
ra_numv6intfs(void)23443094Samaguire ra_numv6intfs(void)
23453094Samaguire {
23463094Samaguire static int num = -1;
23473094Samaguire int ipsock;
23483094Samaguire struct lifnum lifn;
23493094Samaguire
23503094Samaguire if (num != -1)
23513094Samaguire return (num);
23523094Samaguire
23533094Samaguire if ((ipsock = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) {
23543094Samaguire (void) fprintf(stderr,
23553094Samaguire gettext("%1$s: unable to open %2$s: %3$s\n"),
23563094Samaguire myname, IP_DEV_NAME, strerror(errno));
23573094Samaguire return (0);
23583094Samaguire }
23593094Samaguire lifn.lifn_family = AF_INET6;
23603094Samaguire lifn.lifn_flags = 0;
23613094Samaguire
23623094Samaguire if (ioctl(ipsock, SIOCGLIFNUM, &lifn) == -1) {
23633094Samaguire (void) close(ipsock);
23643094Samaguire return (0);
23653094Samaguire }
23663094Samaguire (void) close(ipsock);
23673094Samaguire
23683094Samaguire return (num = lifn.lifn_count);
23693094Samaguire }
23703094Samaguire
23713094Samaguire /*
23723048Samaguire * Parse the configuration file and fill the ra_opts array with opt_value
23733048Samaguire * and opt_default_value values, and the ra_vars array with var_value and
23743048Samaguire * var_default_value values. Then copy aside routing.conf so it will not
23753048Samaguire * be read by future invokations of routeadm.
23763048Samaguire */
23773048Samaguire static int
ra_parseconf(void)23783048Samaguire ra_parseconf(void)
23793048Samaguire {
23803048Samaguire FILE *fp;
23813048Samaguire uint_t lineno;
23823048Samaguire char line[RA_MAX_CONF_LINE];
23833048Samaguire char *cp, *confstr;
23843048Samaguire raopt_t *raopt;
23853048Samaguire ravar_t *ravar;
23863048Samaguire
23873048Samaguire if ((fp = fopen(RA_CONF_FILE, "r")) == NULL) {
23883048Samaguire /*
23893048Samaguire * There's no config file, so we simply return as there
23903048Samaguire * is no work to do.
23913048Samaguire */
23923048Samaguire return (0);
23933048Samaguire }
23943048Samaguire
23953048Samaguire for (lineno = 1; fgets(line, sizeof (line), fp) != NULL; lineno++) {
23963048Samaguire if (line[strlen(line) - 1] == '\n')
23973048Samaguire line[strlen(line) - 1] = '\0';
23983048Samaguire
23993048Samaguire cp = line;
24003048Samaguire
24013048Samaguire /* Skip leading whitespace */
24023048Samaguire while (isspace(*cp))
24033048Samaguire cp++;
24043048Samaguire
24053048Samaguire /* Skip comment lines and empty lines */
24063048Samaguire if (*cp == '#' || *cp == '\0')
24073048Samaguire continue;
24083048Samaguire
24093048Samaguire /*
24103048Samaguire * Anything else must be of the form:
24113048Samaguire * <option> <value> <default_value>
24123048Samaguire */
24133048Samaguire if ((confstr = strtok(cp, " ")) == NULL) {
24143048Samaguire (void) fprintf(stderr,
24153048Samaguire gettext("%1$s: %2$s: invalid entry on line %3$d\n"),
24163048Samaguire myname, RA_CONF_FILE, lineno);
24173048Samaguire continue;
24183048Samaguire }
24193048Samaguire
24203048Samaguire if ((raopt = ra_str2opt(confstr)) != NULL) {
24213048Samaguire if (ra_parseopt(confstr, lineno, raopt) != 0) {
24223048Samaguire (void) fclose(fp);
24233048Samaguire return (-1);
24243048Samaguire }
24253048Samaguire } else if ((ravar = ra_str2var(confstr)) != NULL) {
24263048Samaguire if (ra_parsevar(confstr, ravar) != 0) {
24273048Samaguire (void) fclose(fp);
24283048Samaguire return (-1);
24293048Samaguire }
24303048Samaguire } else {
24313048Samaguire (void) fprintf(stderr,
24323048Samaguire gettext("%1$s: %2$s: invalid option name on "
24333048Samaguire "line %3$d\n"),
24343048Samaguire myname, RA_CONF_FILE, lineno);
24353048Samaguire continue;
24363048Samaguire }
24373048Samaguire }
24383048Samaguire
24393048Samaguire (void) fclose(fp);
24403048Samaguire
24413048Samaguire return (1);
24423048Samaguire }
24433048Samaguire
24443048Samaguire static int
ra_parseopt(char * confstr,int lineno,raopt_t * raopt)24453048Samaguire ra_parseopt(char *confstr, int lineno, raopt_t *raopt)
24463048Samaguire {
24473048Samaguire oval_t oval, d_oval;
24483048Samaguire
24493048Samaguire if ((confstr = strtok(NULL, " ")) == NULL) {
24503048Samaguire (void) fprintf(stderr,
24513048Samaguire gettext("%1$s: %2$s: missing value on line %3$d\n"),
24523048Samaguire myname, RA_CONF_FILE, lineno);
24533048Samaguire return (0);
24543048Samaguire }
24553048Samaguire if ((oval = ra_str2oval(confstr)) == OPT_INVALID) {
24563048Samaguire (void) fprintf(stderr,
24573048Samaguire gettext("%1$s: %2$s: invalid option "
24583048Samaguire "value on line %3$d\n"),
24593048Samaguire myname, RA_CONF_FILE, lineno);
24603048Samaguire return (0);
24613048Samaguire }
24623048Samaguire if (oval != OPT_DEFAULT)
24633048Samaguire raopt->opt_enabled = oval == OPT_ENABLED;
24643048Samaguire
24653048Samaguire if ((confstr = strtok(NULL, " ")) == NULL) {
24663048Samaguire (void) fprintf(stderr,
24673048Samaguire gettext("%1$s: %2$s: missing revert "
24683048Samaguire "value on line %3$d\n"),
24693048Samaguire myname, RA_CONF_FILE, lineno);
24703048Samaguire return (0);
24713048Samaguire }
24723048Samaguire if ((d_oval = ra_str2oval(confstr)) == OPT_INVALID) {
24733048Samaguire (void) fprintf(stderr,
24743048Samaguire gettext("%1$s: %2$s: invalid revert "
24753048Samaguire "value on line %3$d\n"),
24763048Samaguire myname, RA_CONF_FILE, lineno, confstr);
24773048Samaguire return (0);
24783048Samaguire }
24793048Samaguire raopt->opt_default_enabled = d_oval == OPT_ENABLED;
24803048Samaguire if (oval == OPT_DEFAULT)
24813048Samaguire raopt->opt_enabled = d_oval == OPT_ENABLED;
2482*3294Samaguire
2483*3294Samaguire /*
2484*3294Samaguire * Set ipv4(6)-routing-set property as appropriate on upgrading
2485*3294Samaguire * routing.conf. If option was default, set this value to false,
2486*3294Samaguire * as this indicates the administrator has not explicitly enabled
2487*3294Samaguire * or disabled ipv4(6)-routing. The ipv4-routing-set value is used
2488*3294Samaguire * in the routing-setup service, and if it is false, ipv4-routing
2489*3294Samaguire * is enabled in the case where no default route can be determined.
2490*3294Samaguire */
2491*3294Samaguire if (raopt->opt_flags & (RA_SVC_FLAG_IPV4_ROUTING |
2492*3294Samaguire RA_SVC_FLAG_IPV6_ROUTING)) {
2493*3294Samaguire if (ra_smf_cb(oval == OPT_DEFAULT ? ra_routing_opt_unset_cb :
2494*3294Samaguire ra_routing_opt_set_cb, raopt->opt_default_fmri, raopt)
2495*3294Samaguire == -1)
2496*3294Samaguire return (-1);
2497*3294Samaguire }
24983048Samaguire return (0);
24993048Samaguire }
25003048Samaguire
25013048Samaguire static int
ra_parsevar(char * confstr,ravar_t * ravar)25023048Samaguire ra_parsevar(char *confstr, ravar_t *ravar)
25033048Samaguire {
25043048Samaguire confstr = strtok(NULL, "=");
25053048Samaguire if (confstr == NULL) {
25063048Samaguire /*
25073048Samaguire * This isn't an error condition, it simply means that the
25083048Samaguire * variable has no value.
25093048Samaguire */
25103048Samaguire ravar->var_value = NULL;
25113048Samaguire return (0);
25123048Samaguire }
25133048Samaguire
25143048Samaguire if ((ravar->var_value = strdup(confstr)) == NULL) {
25153048Samaguire (void) fprintf(stderr, gettext("%s: "
25163048Samaguire "unable to allocate memory\n"), myname);
25173048Samaguire return (-1);
25183048Samaguire }
25193048Samaguire return (0);
25203048Samaguire }
25213048Samaguire
25223048Samaguire /* Convert a string to an option value. */
25233048Samaguire static oval_t
ra_str2oval(const char * valstr)25243048Samaguire ra_str2oval(const char *valstr)
25253048Samaguire {
25263048Samaguire if (strcmp(valstr, "enabled") == 0)
25273048Samaguire return (OPT_ENABLED);
25283048Samaguire else if (strcmp(valstr, "disabled") == 0)
25293048Samaguire return (OPT_DISABLED);
25303048Samaguire else if (strcmp(valstr, "default") == 0)
25313048Samaguire return (OPT_DEFAULT);
25323048Samaguire return (OPT_INVALID);
25333048Samaguire }
25343048Samaguire
25353048Samaguire static raopt_t *
ra_str2opt(const char * optnamestr)25363048Samaguire ra_str2opt(const char *optnamestr)
25373048Samaguire {
25383048Samaguire int i;
25393048Samaguire
25403048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) {
25413048Samaguire if (strcmp(optnamestr, ra_opts[i].opt_name) == 0)
25423048Samaguire break;
25433048Samaguire }
25443048Samaguire if (ra_opts[i].opt_name == NULL)
25453048Samaguire return (NULL);
25463048Samaguire return (&ra_opts[i]);
25473048Samaguire }
25483048Samaguire
25493048Samaguire /*
25503048Samaguire * Reset all option values previously gathered to B_FALSE.
25513048Samaguire */
25523048Samaguire static void
ra_resetopts(void)25533048Samaguire ra_resetopts(void)
25543048Samaguire {
25553048Samaguire int i;
25563048Samaguire
25573048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) {
25583048Samaguire ra_opts[i].opt_enabled = B_FALSE;
25593048Samaguire ra_opts[i].opt_default_enabled = B_FALSE;
25603048Samaguire }
25613048Samaguire }
25623048Samaguire
25633048Samaguire static ravar_t *
ra_str2var(const char * varnamestr)25643048Samaguire ra_str2var(const char *varnamestr)
25653048Samaguire {
25663048Samaguire int i;
25673048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) {
25683048Samaguire if (strcmp(varnamestr, ra_vars[i].var_name) == 0)
25693048Samaguire break;
25703048Samaguire }
25713048Samaguire if (ra_vars[i].var_name == NULL)
25723048Samaguire return (NULL);
25733048Samaguire return (&ra_vars[i]);
25743048Samaguire }
25753048Samaguire
25763048Samaguire /*
25773048Samaguire * Reset variable values previously gathered to NULL.
25783048Samaguire */
25793048Samaguire static void
ra_resetvars(const char * proto)25803048Samaguire ra_resetvars(const char *proto)
25813048Samaguire {
25823048Samaguire int i;
25833048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) {
25843048Samaguire if (proto != NULL &&
25853048Samaguire !VAR_PROTO_MATCH(ra_vars[i].var_name, proto))
25863048Samaguire continue;
25873048Samaguire if (ra_vars[i].var_value != NULL)
25883048Samaguire free(ra_vars[i].var_value);
25893048Samaguire ra_vars[i].var_value = NULL;
25903048Samaguire if (ra_vars[i].var_default_value != NULL)
25913048Samaguire free(ra_vars[i].var_default_value);
25923048Samaguire ra_vars[i].var_default_value = NULL;
25933048Samaguire }
25943048Samaguire }
25953048Samaguire
25963048Samaguire /*
25973048Samaguire * Given an option name, this function provides an internationalized, human
25983048Samaguire * readable version of the option name.
25993048Samaguire */
26003048Samaguire static char *
ra_intloptname(const char * optname)26013048Samaguire ra_intloptname(const char *optname)
26023048Samaguire {
26033048Samaguire if (strcmp(optname, RA_OPT_IPV4_FORWARDING) == 0)
26043048Samaguire return (gettext("IPv4 forwarding"));
26053048Samaguire else if (strcmp(optname, RA_OPT_IPV4_ROUTING) == 0)
26063048Samaguire return (gettext("IPv4 routing"));
26073048Samaguire else if (strcmp(optname, RA_OPT_IPV6_FORWARDING) == 0)
26083048Samaguire return (gettext("IPv6 forwarding"));
26093048Samaguire else if (strcmp(optname, RA_OPT_IPV6_ROUTING) == 0)
26103048Samaguire return (gettext("IPv6 routing"));
26113048Samaguire else if (strcmp(optname, RA_VAR_IPV4_ROUTING_DAEMON) == 0)
26123048Samaguire return (gettext("IPv4 routing daemon"));
26133048Samaguire else if (strcmp(optname, RA_VAR_IPV4_ROUTING_DAEMON_ARGS) == 0)
26143048Samaguire return (gettext("IPv4 routing daemon args"));
26153048Samaguire else if (strcmp(optname, RA_VAR_IPV4_ROUTING_STOP_CMD) == 0)
26163048Samaguire return (gettext("IPv4 routing daemon stop"));
26173048Samaguire else if (strcmp(optname, RA_VAR_IPV6_ROUTING_DAEMON) == 0)
26183048Samaguire return (gettext("IPv6 routing daemon"));
26193048Samaguire else if (strcmp(optname, RA_VAR_IPV6_ROUTING_DAEMON_ARGS) == 0)
26203048Samaguire return (gettext("IPv6 routing daemon args"));
26213048Samaguire else if (strcmp(optname, RA_VAR_IPV6_ROUTING_STOP_CMD) == 0)
26223048Samaguire return (gettext("IPv6 routing daemon stop"));
26233048Samaguire else if (strcmp(optname, RA_VAR_ROUTING_SVCS) == 0)
26243048Samaguire return (gettext("Routing services"));
26253048Samaguire /*
26263048Samaguire * If we get here, there's a bug and someone should trip over this
26273048Samaguire * NULL pointer.
26283048Samaguire */
26293048Samaguire return (NULL);
26303048Samaguire }
2631