1*3048Samaguire /* 2*3048Samaguire * CDDL HEADER START 3*3048Samaguire * 4*3048Samaguire * The contents of this file are subject to the terms of the 5*3048Samaguire * Common Development and Distribution License (the "License"). 6*3048Samaguire * You may not use this file except in compliance with the License. 7*3048Samaguire * 8*3048Samaguire * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3048Samaguire * or http://www.opensolaris.org/os/licensing. 10*3048Samaguire * See the License for the specific language governing permissions 11*3048Samaguire * and limitations under the License. 12*3048Samaguire * 13*3048Samaguire * When distributing Covered Code, include this CDDL HEADER in each 14*3048Samaguire * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3048Samaguire * If applicable, add the following below this CDDL HEADER, with the 16*3048Samaguire * fields enclosed by brackets "[]" replaced with your own identifying 17*3048Samaguire * information: Portions Copyright [yyyy] [name of copyright owner] 18*3048Samaguire * 19*3048Samaguire * CDDL HEADER END 20*3048Samaguire */ 21*3048Samaguire /* 22*3048Samaguire * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*3048Samaguire * Use is subject to license terms. 24*3048Samaguire */ 25*3048Samaguire 26*3048Samaguire #pragma ident "%Z%%M% %I% %E% SMI" 27*3048Samaguire 28*3048Samaguire #include <stdio.h> 29*3048Samaguire #include <string.h> 30*3048Samaguire #include <stdlib.h> 31*3048Samaguire #include <unistd.h> 32*3048Samaguire #include <limits.h> 33*3048Samaguire #include <ctype.h> 34*3048Samaguire #include <stropts.h> 35*3048Samaguire #include <errno.h> 36*3048Samaguire #include <libintl.h> 37*3048Samaguire #include <locale.h> 38*3048Samaguire #include <fcntl.h> 39*3048Samaguire #include <sys/types.h> 40*3048Samaguire #include <sys/stat.h> 41*3048Samaguire #include <libscf.h> 42*3048Samaguire #include <libscf_priv.h> 43*3048Samaguire #include <libuutil.h> 44*3048Samaguire 45*3048Samaguire /* 46*3048Samaguire * This program moves routing management under SMF. We do this by giving 47*3048Samaguire * routeadm options that allow interaction with SMF services. These include: 48*3048Samaguire * - setting the routing services routeadm will enable 49*3048Samaguire * # routeadm -s routing-svcs="fmri [fmri...]" 50*3048Samaguire * where each fmri is an SMF routing service. 51*3048Samaguire * - changing properties of routing services 52*3048Samaguire * # routeadm -m fmri key=value [key=value...] 53*3048Samaguire * - listing routing daemon properties 54*3048Samaguire * # routeadm -l fmri 55*3048Samaguire * where all properties in the "routing" property group are listed. 56*3048Samaguire * 57*3048Samaguire * By providing legacy routing services (legacy-routing:ipv4 and ipv6), we 58*3048Samaguire * can also support running of routing daemons with no SMF service under SMF. 59*3048Samaguire * Specifying a routing daemon with no SMF counterpart results in the 60*3048Samaguire * daemon, it`s arguments and stop command being set in the appropriate instance 61*3048Samaguire * to be picked up by start/stop methods. 62*3048Samaguire * 63*3048Samaguire * Internally, routeadm keeps track of routing services by setting the 64*3048Samaguire * "current-routing-svc" property to "true" in the services it manages. 65*3048Samaguire * So for example, running 66*3048Samaguire * # routeadm -s routing-svcs="route:default ripng:default" 67*3048Samaguire * sets this variable in each instance specified. If the user specifies a 68*3048Samaguire * non-SMF routing daemon via 69*3048Samaguire * # routeadm -s ipv4-routing-daemon=/usr/sbin/mydaemon 70*3048Samaguire * the variable will be set for the legacy-routing:ipv4 instance. 71*3048Samaguire * 72*3048Samaguire * In order to ensure that the SMF versions of routing daemons are used 73*3048Samaguire * where possible, routeadm will check the daemons specified in 74*3048Samaguire * ipv4-routing-daemon/ipv6-routing-daemon to determine if there is an 75*3048Samaguire * SMF counterpart. If so, rather than running the legacy service 76*3048Samaguire * we move configuration, specifically the associated daemon arguments 77*3048Samaguire * to the SMF counterpart. From there, when the daemon is enabled, it 78*3048Samaguire * will pick up the daemon arguments setting, transfer the argument string 79*3048Samaguire * to the appropriate properties and run the service. 80*3048Samaguire * 81*3048Samaguire * To support the semantics of routeadm -e (enable at next boot) through SMF, 82*3048Samaguire * we make use of temporary state changes, which last only until reboot. 83*3048Samaguire * For example, if a service is disabled, and it is to be enabled via 84*3048Samaguire * routeadm -e, we simply change the disable to a temporary disable, 85*3048Samaguire * and set the persistent enabled value to true. This ensures the daemon 86*3048Samaguire * will run at next boot, but not now. The reverse is true for disabling 87*3048Samaguire * enabled instances (and if the daemon is enabled when we issue the enable, 88*3048Samaguire * we do nothing since it is already in the desired state). 89*3048Samaguire * 90*3048Samaguire * Since the code is quite involved, we provide a guide to the more complex 91*3048Samaguire * actions taken in response to user commands. 92*3048Samaguire * 93*3048Samaguire * routeadm -e[d] ipv4[6]-routing[forwarding] 94*3048Samaguire * 95*3048Samaguire * In this case, the goal is to prepare the configured routing daemons 96*3048Samaguire * (specified through routeadm -s routing-svcs="...") or forwarding 97*3048Samaguire * services to switch on (-e) or of (-d) at next boot. 98*3048Samaguire * 99*3048Samaguire * Since this operation must be applied to multiple services in the 100*3048Samaguire * routing daemon case (as opposed to the single ipv4[6]-forwarding 101*3048Samaguire * service), we make use of the scf_walk_fmri() function, which 102*3048Samaguire * applies a callback function to all matching functions. In the case 103*3048Samaguire * of the routing daemons, we pass in a NULL signifying that all 104*3048Samaguire * instances should be walked (we then weed out the relevant routing 105*3048Samaguire * services through presence of the routeadm/protocol property). In 106*3048Samaguire * the case of enable, a routing service is enabled IFF it has the 107*3048Samaguire * previously-mentioned property - with an appropriate value (i.e. ipv4 108*3048Samaguire * for "routeadm -e ipv4-routing") - and it has routeadm/curr-routing-svc 109*3048Samaguire * property set to true (this is set by other operations such as 110*3048Samaguire * routeadm -s routing-svcs="..."). Then, smf_enable_instance() or 111*3048Samaguire * smf_disable_instance() is called, setting the temporary state to 112*3048Samaguire * the current state of the service. This then allows setting of 113*3048Samaguire * general/enabled value to next-boot value. In the case of disabling 114*3048Samaguire * ipv4[6]-routing, all valid ipv4[6] routing daemons are prepared 115*3048Samaguire * for next-boot disable, not just those specified via routing-svcs (this 116*3048Samaguire * means that if the user enables routing daemons with "svcadm enable", 117*3048Samaguire * disabling global routing does really switch off all routing daemons). 118*3048Samaguire * 119*3048Samaguire * This is implemented through the ra_get_set_opt_common_cb() function, 120*3048Samaguire * called by the ra_set_persistent_opt_cb() function. The same 121*3048Samaguire * function can be used for both routing and forwarding options, in the 122*3048Samaguire * latter case we simply provide the specific FMRI of the forwarding 123*3048Samaguire * service in question (ipv4-forwarding or ipv6-forwarding), and dispense 124*3048Samaguire * with the eligibility tests we need to weed out the routing services 125*3048Samaguire * from the rest. 126*3048Samaguire * 127*3048Samaguire * Before we initiate the "enable" however, we must check routing daemons 128*3048Samaguire * specified via the legacy variables (ipv4-routing-daemon etc). 129*3048Samaguire * If they map to SMF routing services, we wish to transfer their 130*3048Samaguire * configuration to the corresponding services and use them instead of 131*3048Samaguire * the legacy services. To do this, we need to match the daemon program 132*3048Samaguire * against the routeadm/daemon property of each routing daemon (we use 133*3048Samaguire * scf_walk_fmri() and the routeadm/protocol property again to identify 134*3048Samaguire * daemons). If a match is found, the daemon arguments are transferred 135*3048Samaguire * to the appropriate service`s daemon-args property, to be picked up 136*3048Samaguire * by it`s start method and converted into appropriate property values. 137*3048Samaguire * This is accomplished by ra_check_legacy_daemons(), and the callback 138*3048Samaguire * operation is carried out by ra_upgrade_legacy_daemons_cb(). If the 139*3048Samaguire * daemon was not upgraded, we need to mark the legacy-routing:ipv4[6] 140*3048Samaguire * instance to be enabled (by routeadm -e), since it now must run the 141*3048Samaguire * un-upgradeable legacy daemon. 142*3048Samaguire * 143*3048Samaguire * routeadm -l fmri 144*3048Samaguire * 145*3048Samaguire * Lists all properties and values in the routing property group associated 146*3048Samaguire * with instance fmri. We simply walk through the composed property 147*3048Samaguire * group, displaying all values. See ra_list_props_cb(). 148*3048Samaguire * 149*3048Samaguire * routeadm -m fmri key=value ... 150*3048Samaguire * 151*3048Samaguire * Modify property values in the routing property group. If the same 152*3048Samaguire * key is used more than once, multiple property values are set for that 153*3048Samaguire * property. Properties must exist in the composed property group, but 154*3048Samaguire * will only ever be set at the instance level to prevent multiple 155*3048Samaguire * instances inheriting the property in error. See ra_modify_props_cb(). 156*3048Samaguire * 157*3048Samaguire * routeadm -s var=value 158*3048Samaguire * 159*3048Samaguire * In all cases bar the routing-svcs variable, this simply involves 160*3048Samaguire * setting the appropriate SMF property value for the variable. The 161*3048Samaguire * routing-svcs case is more complex, since we would like operations 162*3048Samaguire * like the following to have intuitive effects: 163*3048Samaguire * # routeadm -s routing-svcs=route -e ipv4-routing -u 164*3048Samaguire * # routeadm -s routing-svcs=rdisc -u 165*3048Samaguire * i.e., in the end, rdisc is the only routing service running. To 166*3048Samaguire * accomplish this switchover, we need to disable the old routing-svcs 167*3048Samaguire * and enable the new, marking the latter with the curr-routing-svc 168*3048Samaguire * property so that routeadm -e will pick them up. This is carried 169*3048Samaguire * out by the ra_update_routing_svcs() function. 170*3048Samaguire * 171*3048Samaguire * routeadm -R alt_root ... 172*3048Samaguire * 173*3048Samaguire * Used to support use of routeadm in Custom Jumpstart scripts, this 174*3048Samaguire * option causes all subsequent commands to be appended to the 175*3048Samaguire * /var/svc/profile/upgrade file, which is run on the subsequent boot. 176*3048Samaguire * This is done because the SMF repository is not available to make 177*3048Samaguire * the modifications to property values required in routeadm operations. 178*3048Samaguire * 179*3048Samaguire * routeadm -u 180*3048Samaguire * 181*3048Samaguire * Update applies the "next boot" state to the current system. Here 182*3048Samaguire * we simply take the persistent state (general/enabled value) and 183*3048Samaguire * make it the current state through smf_enable_instance() or 184*3048Samaguire * smf_disable_instance() as appropriate (these calls, without the 185*3048Samaguire * temporary flag set, delete the general_ovr/enabled property). 186*3048Samaguire */ 187*3048Samaguire 188*3048Samaguire #define RA_OPT_IPV4_ROUTING "ipv4-routing" 189*3048Samaguire #define RA_OPT_IPV6_ROUTING "ipv6-routing" 190*3048Samaguire #define RA_OPT_IPV4_FORWARDING "ipv4-forwarding" 191*3048Samaguire #define RA_OPT_IPV6_FORWARDING "ipv6-forwarding" 192*3048Samaguire 193*3048Samaguire #define IS_ROUTING_OPT(opt) (strcmp(opt, RA_OPT_IPV4_ROUTING) == 0 || \ 194*3048Samaguire strcmp(opt, RA_OPT_IPV6_ROUTING) == 0) 195*3048Samaguire 196*3048Samaguire #define RA_VAR_IPV4_ROUTING_DAEMON "ipv4-routing-daemon" 197*3048Samaguire #define RA_VAR_IPV4_ROUTING_DAEMON_ARGS "ipv4-routing-daemon-args" 198*3048Samaguire #define RA_VAR_IPV4_ROUTING_STOP_CMD "ipv4-routing-stop-cmd" 199*3048Samaguire #define RA_VAR_IPV6_ROUTING_DAEMON "ipv6-routing-daemon" 200*3048Samaguire #define RA_VAR_IPV6_ROUTING_DAEMON_ARGS "ipv6-routing-daemon-args" 201*3048Samaguire #define RA_VAR_IPV6_ROUTING_STOP_CMD "ipv6-routing-stop-cmd" 202*3048Samaguire #define RA_VAR_ROUTING_SVCS "routing-svcs" 203*3048Samaguire 204*3048Samaguire 205*3048Samaguire #define RA_INSTANCE_ALL NULL 206*3048Samaguire #define RA_INSTANCE_ROUTING_SETUP "svc:/network/routing-setup:default" 207*3048Samaguire #define RA_INSTANCE_IPV4_FORWARDING "svc:/network/ipv4-forwarding:default" 208*3048Samaguire #define RA_INSTANCE_IPV6_FORWARDING "svc:/network/ipv6-forwarding:default" 209*3048Samaguire #define RA_INSTANCE_LEGACY_ROUTING_IPV4 \ 210*3048Samaguire "svc:/network/routing/legacy-routing:ipv4" 211*3048Samaguire #define RA_INSTANCE_LEGACY_ROUTING_IPV6 \ 212*3048Samaguire "svc:/network/routing/legacy-routing:ipv6" 213*3048Samaguire 214*3048Samaguire #define RA_PG_ROUTEADM "routeadm" 215*3048Samaguire #define RA_PROP_CURR_ROUTING_SVC "current-routing-svc" 216*3048Samaguire #define RA_PROP_ROUTING_SVCS "routing-svcs" 217*3048Samaguire #define RA_PROP_DEFAULT_ROUTING_SVCS "default-routing-svcs" 218*3048Samaguire #define RA_PROP_PROTO "protocol" 219*3048Samaguire #define RA_PROP_DAEMON "daemon" 220*3048Samaguire #define RA_PROP_DEFAULT_DAEMON "default-daemon" 221*3048Samaguire #define RA_PROP_DAEMON_ARGS "daemon-args" 222*3048Samaguire #define RA_PROP_DEFAULT_DAEMON_ARGS "default-daemon-args" 223*3048Samaguire #define RA_PROP_DAEMON_STOP_CMD "daemon-stop-cmd" 224*3048Samaguire #define RA_PROP_DEFAULT_STOP_CMD "default-daemon" 225*3048Samaguire #define RA_PROP_LEGACY_DAEMON "legacy-daemon" 226*3048Samaguire #define RA_PROP_DEFAULT_IPV4_ROUTING "default-ipv4-routing" 227*3048Samaguire #define RA_PROP_DEFAULT_IPV6_ROUTING "default-ipv6-routing" 228*3048Samaguire #define RA_PROP_DEFAULT_IPV4_FORWARDING "default-ipv4-forwarding" 229*3048Samaguire #define RA_PROP_DEFAULT_IPV6_FORWARDING "default-ipv6-forwarding" 230*3048Samaguire #define RA_PROP_IPV4_ROUTING_SET "ipv4-routing-set" 231*3048Samaguire #define RA_PROP_IPV6_ROUTING_SET "ipv6-routing-set" 232*3048Samaguire #define RA_PROP_ROUTING_CONF_READ "routing-conf-read" 233*3048Samaguire 234*3048Samaguire #define RA_PG_ROUTING "routing" 235*3048Samaguire 236*3048Samaguire #define RA_PROPVAL_BOOLEAN_TRUE "true" 237*3048Samaguire #define RA_PROPVAL_BOOLEAN_FALSE "false" 238*3048Samaguire #define RA_PROPVAL_PROTO_IPV4 "ipv4" 239*3048Samaguire #define RA_PROPVAL_PROTO_IPV6 "ipv6" 240*3048Samaguire 241*3048Samaguire #define RA_SVC_FLAG_NONE 0x0 242*3048Samaguire #define RA_SVC_FLAG_IPV4_ROUTING 0x1 243*3048Samaguire #define RA_SVC_FLAG_IPV6_ROUTING 0x2 244*3048Samaguire 245*3048Samaguire #define RA_SMF_UPGRADE_FILE "/var/svc/profile/upgrade" 246*3048Samaguire #define RA_SMF_UPGRADE_MSG " # added by routeadm(1M)" 247*3048Samaguire #define RA_CONF_FILE "/etc/inet/routing.conf" 248*3048Samaguire #define RA_CONF_FILE_OLD "/etc/inet/routing.conf.old" 249*3048Samaguire #define RA_MAX_CONF_LINE 256 250*3048Samaguire 251*3048Samaguire /* 252*3048Samaguire * Option value. Each option requires an FMRI identifying which services 253*3048Samaguire * to run the get_current/persistent scf_walk_fmri() function with, and 254*3048Samaguire * associated flags (to ensure that in the case that multiple services 255*3048Samaguire * match, we select the correct ones). In addition, we specify the FMRI 256*3048Samaguire * and property used to set default option value. The opt_enabled field 257*3048Samaguire * is used to hold retrieved state from get_*_opt_() callbacks and to specify 258*3048Samaguire * desired state for set_*_opt() operations. 259*3048Samaguire */ 260*3048Samaguire 261*3048Samaguire typedef struct raopt { 262*3048Samaguire const char *opt_name; 263*3048Samaguire const char *opt_fmri; 264*3048Samaguire int opt_flags; 265*3048Samaguire boolean_t opt_enabled; 266*3048Samaguire const char *opt_default_fmri; 267*3048Samaguire const char *opt_default_prop; 268*3048Samaguire boolean_t opt_default_enabled; 269*3048Samaguire } raopt_t; 270*3048Samaguire 271*3048Samaguire 272*3048Samaguire raopt_t ra_opts[] = { 273*3048Samaguire { RA_OPT_IPV4_ROUTING, RA_INSTANCE_ALL, RA_SVC_FLAG_IPV4_ROUTING, 274*3048Samaguire B_FALSE, RA_INSTANCE_ROUTING_SETUP, RA_PROP_DEFAULT_IPV4_ROUTING, 275*3048Samaguire B_FALSE }, 276*3048Samaguire { RA_OPT_IPV6_ROUTING, RA_INSTANCE_ALL, RA_SVC_FLAG_IPV6_ROUTING, 277*3048Samaguire B_FALSE, RA_INSTANCE_ROUTING_SETUP, RA_PROP_DEFAULT_IPV6_ROUTING, 278*3048Samaguire B_FALSE }, 279*3048Samaguire { RA_OPT_IPV4_FORWARDING, RA_INSTANCE_IPV4_FORWARDING, RA_SVC_FLAG_NONE, 280*3048Samaguire B_FALSE, RA_INSTANCE_IPV4_FORWARDING, RA_PROP_DEFAULT_IPV4_FORWARDING, 281*3048Samaguire B_FALSE }, 282*3048Samaguire { RA_OPT_IPV6_FORWARDING, RA_INSTANCE_IPV6_FORWARDING, RA_SVC_FLAG_NONE, 283*3048Samaguire B_FALSE, RA_INSTANCE_IPV6_FORWARDING, RA_PROP_DEFAULT_IPV6_FORWARDING, 284*3048Samaguire B_FALSE }, 285*3048Samaguire { NULL, NULL, RA_SVC_FLAG_NONE, B_FALSE, NULL, NULL, B_FALSE } 286*3048Samaguire }; 287*3048Samaguire 288*3048Samaguire typedef enum option_values { 289*3048Samaguire OPT_INVALID, OPT_ENABLED, OPT_DISABLED, OPT_DEFAULT, OPT_UNKNOWN 290*3048Samaguire } oval_t; 291*3048Samaguire 292*3048Samaguire typedef struct ra_var { 293*3048Samaguire const char *var_name; 294*3048Samaguire const char *var_fmri; 295*3048Samaguire const char *var_prop; 296*3048Samaguire char *var_value; 297*3048Samaguire const char *var_default_fmri; 298*3048Samaguire const char *var_default_prop; 299*3048Samaguire char *var_default_value; 300*3048Samaguire } ravar_t; 301*3048Samaguire 302*3048Samaguire ravar_t ra_vars[] = { 303*3048Samaguire { RA_VAR_IPV4_ROUTING_DAEMON, RA_INSTANCE_LEGACY_ROUTING_IPV4, 304*3048Samaguire RA_PROP_DAEMON, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV4, 305*3048Samaguire RA_PROP_DEFAULT_DAEMON, NULL}, 306*3048Samaguire { RA_VAR_IPV4_ROUTING_DAEMON_ARGS, RA_INSTANCE_LEGACY_ROUTING_IPV4, 307*3048Samaguire RA_PROP_DAEMON_ARGS, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV4, 308*3048Samaguire RA_PROP_DEFAULT_DAEMON_ARGS, NULL }, 309*3048Samaguire { RA_VAR_IPV4_ROUTING_STOP_CMD, RA_INSTANCE_LEGACY_ROUTING_IPV4, 310*3048Samaguire RA_PROP_DAEMON_STOP_CMD, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV4, 311*3048Samaguire RA_PROP_DEFAULT_STOP_CMD, NULL }, 312*3048Samaguire { RA_VAR_IPV6_ROUTING_DAEMON, RA_INSTANCE_LEGACY_ROUTING_IPV6, 313*3048Samaguire RA_PROP_DAEMON, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV6, 314*3048Samaguire RA_PROP_DEFAULT_DAEMON, NULL }, 315*3048Samaguire { RA_VAR_IPV6_ROUTING_DAEMON_ARGS, RA_INSTANCE_LEGACY_ROUTING_IPV6, 316*3048Samaguire RA_PROP_DAEMON_ARGS, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV6, 317*3048Samaguire RA_PROP_DEFAULT_DAEMON_ARGS, NULL }, 318*3048Samaguire { RA_VAR_IPV6_ROUTING_STOP_CMD, RA_INSTANCE_LEGACY_ROUTING_IPV6, 319*3048Samaguire RA_PROP_DAEMON_STOP_CMD, NULL, RA_INSTANCE_LEGACY_ROUTING_IPV6, 320*3048Samaguire RA_PROP_DEFAULT_STOP_CMD, NULL }, 321*3048Samaguire { RA_VAR_ROUTING_SVCS, RA_INSTANCE_ROUTING_SETUP, 322*3048Samaguire RA_PROP_ROUTING_SVCS, NULL, RA_INSTANCE_ROUTING_SETUP, 323*3048Samaguire RA_PROP_DEFAULT_ROUTING_SVCS, NULL }, 324*3048Samaguire { NULL, NULL, NULL, NULL, NULL, NULL, NULL } 325*3048Samaguire }; 326*3048Samaguire 327*3048Samaguire char *v_opt[] = { 328*3048Samaguire #define IPV4_ROUTING_DAEMON 0 329*3048Samaguire RA_VAR_IPV4_ROUTING_DAEMON, 330*3048Samaguire #define IPV4_ROUTING_DAEMON_ARGS 1 331*3048Samaguire RA_VAR_IPV4_ROUTING_DAEMON_ARGS, 332*3048Samaguire #define IPV4_ROUTING_STOP_CMD 2 333*3048Samaguire RA_VAR_IPV4_ROUTING_STOP_CMD, 334*3048Samaguire #define IPV6_ROUTING_DAEMON 3 335*3048Samaguire RA_VAR_IPV6_ROUTING_DAEMON, 336*3048Samaguire #define IPV6_ROUTING_DAEMON_ARGS 4 337*3048Samaguire RA_VAR_IPV6_ROUTING_DAEMON_ARGS, 338*3048Samaguire #define IPV6_ROUTING_STOP_CMD 5 339*3048Samaguire RA_VAR_IPV6_ROUTING_STOP_CMD, 340*3048Samaguire #define ROUTING_SVCS 6 341*3048Samaguire RA_VAR_ROUTING_SVCS, 342*3048Samaguire NULL 343*3048Samaguire }; 344*3048Samaguire 345*3048Samaguire #define IS_IPV4_VAR(varname) (strncmp(varname, "ipv4", 4) == 0) 346*3048Samaguire #define IS_IPV6_VAR(varname) (strncmp(varname, "ipv6", 4) == 0) 347*3048Samaguire #define VAR_PROTO_MATCH(varname, proto) (strncmp(varname, proto, 4) == 0) 348*3048Samaguire #define IPV4_VARS_UNSET \ 349*3048Samaguire (strtok(ra_vars[IPV4_ROUTING_DAEMON].var_value, " \t") == NULL && \ 350*3048Samaguire strtok(ra_vars[IPV4_ROUTING_DAEMON_ARGS].var_value, " \t") == NULL && \ 351*3048Samaguire strtok(ra_vars[IPV4_ROUTING_STOP_CMD].var_value, " \t") == NULL) 352*3048Samaguire 353*3048Samaguire #define IPV6_VARS_UNSET \ 354*3048Samaguire (strtok(ra_vars[IPV6_ROUTING_DAEMON].var_value, " \t") == NULL && \ 355*3048Samaguire strtok(ra_vars[IPV6_ROUTING_DAEMON_ARGS].var_value, " \t") == NULL && \ 356*3048Samaguire strtok(ra_vars[IPV6_ROUTING_STOP_CMD].var_value, " \t") == NULL) 357*3048Samaguire 358*3048Samaguire /* 359*3048Samaguire * Structure used in modify operations to tie property name and multiple values 360*3048Samaguire * together. 361*3048Samaguire */ 362*3048Samaguire typedef struct ra_prop { 363*3048Samaguire char *prop_name; 364*3048Samaguire char **prop_values; 365*3048Samaguire int prop_numvalues; 366*3048Samaguire } ra_prop_t; 367*3048Samaguire 368*3048Samaguire typedef int (*ra_smf_cb_t)(void *, scf_walkinfo_t *); 369*3048Samaguire 370*3048Samaguire /* Used to store program name */ 371*3048Samaguire static const char *myname; 372*3048Samaguire 373*3048Samaguire static void usage(void); 374*3048Samaguire 375*3048Samaguire static int ra_check_legacy_daemons(void); 376*3048Samaguire static int ra_upgrade_legacy_daemons(void); 377*3048Samaguire static int ra_upgrade_cmd(char, int, char **); 378*3048Samaguire static int ra_update(void); 379*3048Samaguire static int ra_update_routing_svcs(char *); 380*3048Samaguire static int ra_report(boolean_t, const char *); 381*3048Samaguire static int ra_smf_cb(ra_smf_cb_t, const char *, void *); 382*3048Samaguire static int ra_upgrade_from_legacy_conf(void); 383*3048Samaguire static int ra_parseconf(void); 384*3048Samaguire static int ra_parseopt(char *, int, raopt_t *); 385*3048Samaguire static int ra_parsevar(char *, ravar_t *); 386*3048Samaguire static oval_t ra_str2oval(const char *); 387*3048Samaguire static raopt_t *ra_str2opt(const char *); 388*3048Samaguire static void ra_resetopts(void); 389*3048Samaguire static ravar_t *ra_str2var(const char *); 390*3048Samaguire static void ra_resetvars(const char *); 391*3048Samaguire static char *ra_intloptname(const char *); 392*3048Samaguire 393*3048Samaguire /* Callback for upgrade of legacy daemons */ 394*3048Samaguire static int ra_upgrade_legacy_daemons_cb(void *, scf_walkinfo_t *); 395*3048Samaguire 396*3048Samaguire /* Callbacks used to set/retieve routing options */ 397*3048Samaguire static int ra_set_current_opt_cb(void *, scf_walkinfo_t *); 398*3048Samaguire static int ra_set_persistent_opt_cb(void *, scf_walkinfo_t *); 399*3048Samaguire static int ra_set_default_opt_cb(void *, scf_walkinfo_t *); 400*3048Samaguire static int ra_get_current_opt_cb(void *, scf_walkinfo_t *); 401*3048Samaguire static int ra_get_persistent_opt_cb(void *, scf_walkinfo_t *); 402*3048Samaguire static int ra_get_default_opt_cb(void *, scf_walkinfo_t *); 403*3048Samaguire static int ra_get_set_opt_common_cb(raopt_t *, scf_walkinfo_t *, boolean_t, 404*3048Samaguire boolean_t); 405*3048Samaguire 406*3048Samaguire /* Callbacks used to set/retrieve routing variables */ 407*3048Samaguire static int ra_set_persistent_var_cb(void *, scf_walkinfo_t *); 408*3048Samaguire static int ra_get_persistent_var_cb(void *, scf_walkinfo_t *); 409*3048Samaguire static int ra_get_default_var_cb(void *, scf_walkinfo_t *); 410*3048Samaguire static int ra_mark_routing_svcs_cb(void *, scf_walkinfo_t *); 411*3048Samaguire 412*3048Samaguire /* Callbacks used to list/set daemon properties and list daemons and states. */ 413*3048Samaguire static int ra_list_props_cb(void *, scf_walkinfo_t *); 414*3048Samaguire static int ra_modify_props_cb(void *, scf_walkinfo_t *); 415*3048Samaguire static int ra_print_state_cb(void *, scf_walkinfo_t *); 416*3048Samaguire 417*3048Samaguire /* Utility functions for SMF operations */ 418*3048Samaguire static int ra_get_pg(scf_handle_t *, scf_instance_t *, const char *, 419*3048Samaguire boolean_t, boolean_t, scf_propertygroup_t **); 420*3048Samaguire static int ra_get_boolean_prop(scf_handle_t *, scf_instance_t *, 421*3048Samaguire const char *, const char *, boolean_t, boolean_t, boolean_t *); 422*3048Samaguire static int ra_get_single_prop_as_string(scf_handle_t *, scf_instance_t *, 423*3048Samaguire const char *, const char *, boolean_t, boolean_t, scf_type_t *, char **); 424*3048Samaguire static int ra_get_prop_as_string(scf_handle_t *, scf_instance_t *, 425*3048Samaguire const char *, const char *, boolean_t, boolean_t, scf_type_t *, int *, 426*3048Samaguire char ***); 427*3048Samaguire static void ra_free_prop_values(int, char **); 428*3048Samaguire static int ra_set_boolean_prop(scf_handle_t *, scf_instance_t *, 429*3048Samaguire const char *, const char *, boolean_t, boolean_t); 430*3048Samaguire static int ra_set_prop_from_string(scf_handle_t *, scf_instance_t *, 431*3048Samaguire const char *, const char *, scf_type_t, boolean_t, int, 432*3048Samaguire const char **); 433*3048Samaguire 434*3048Samaguire static void 435*3048Samaguire usage(void) 436*3048Samaguire { 437*3048Samaguire (void) fprintf(stderr, gettext( 438*3048Samaguire "usage: %1$s [-p] [-R <root-dir>]\n" 439*3048Samaguire " %1$s [-e <option>] [-d <option>] [-r <option>]\n" 440*3048Samaguire " [-l <FMRI>] [-m <FMRI> key=value [...]]\n" 441*3048Samaguire " [-s <var>=<val>] [-R <root-dir>]\n" 442*3048Samaguire " %1$s -u\n\n" 443*3048Samaguire " <option> is one of:\n" 444*3048Samaguire " ipv4-forwarding\n" 445*3048Samaguire " ipv4-routing\n" 446*3048Samaguire " ipv6-forwarding\n" 447*3048Samaguire " ipv6-routing\n\n" 448*3048Samaguire " <var> is one of:\n" 449*3048Samaguire " ipv4-routing-daemon\n" 450*3048Samaguire " ipv4-routing-daemon-args\n" 451*3048Samaguire " ipv4-routing-stop-cmd\n" 452*3048Samaguire " ipv6-routing-daemon\n" 453*3048Samaguire " ipv6-routing-daemon-args\n" 454*3048Samaguire " ipv6-routing-stop-cmd\n" 455*3048Samaguire " routing-svcs\n"), myname); 456*3048Samaguire } 457*3048Samaguire 458*3048Samaguire int 459*3048Samaguire main(int argc, char *argv[]) 460*3048Samaguire { 461*3048Samaguire int opt, opt_index, numargs, status = 0; 462*3048Samaguire int numvalues, i; 463*3048Samaguire ssize_t keylen; 464*3048Samaguire boolean_t modify = B_FALSE, report = B_TRUE, update = B_FALSE; 465*3048Samaguire boolean_t alt_root_set = B_FALSE; 466*3048Samaguire boolean_t parseable = B_FALSE; 467*3048Samaguire char *key, *nk, *keyend, *val, **vals, *options, *fmri; 468*3048Samaguire char *parseopt = NULL; 469*3048Samaguire raopt_t *raopt; 470*3048Samaguire ravar_t *ravar; 471*3048Samaguire ra_prop_t raprop; 472*3048Samaguire 473*3048Samaguire myname = argv[0]; 474*3048Samaguire 475*3048Samaguire (void) setlocale(LC_ALL, ""); 476*3048Samaguire 477*3048Samaguire #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 478*3048Samaguire #define TEXT_DOMAIN "SYS_TEST" 479*3048Samaguire #endif 480*3048Samaguire 481*3048Samaguire (void) textdomain(TEXT_DOMAIN); 482*3048Samaguire 483*3048Samaguire /* 484*3048Samaguire * Before processing any options, we parse /etc/inet/routing.conf 485*3048Samaguire * (if present) and transfer values to SMF. 486*3048Samaguire */ 487*3048Samaguire if (ra_upgrade_from_legacy_conf() == -1) 488*3048Samaguire exit(EXIT_FAILURE); 489*3048Samaguire while ((opt = getopt(argc, argv, ":d:e:l:m:p:R:r:s:u")) != EOF) { 490*3048Samaguire switch (opt) { 491*3048Samaguire case 'd': 492*3048Samaguire case 'e': 493*3048Samaguire case 'r': 494*3048Samaguire if (alt_root_set) { 495*3048Samaguire if (ra_upgrade_cmd(opt, 1, &optarg) != 0) 496*3048Samaguire exit(EXIT_FAILURE); 497*3048Samaguire modify = B_TRUE; 498*3048Samaguire break; 499*3048Samaguire } 500*3048Samaguire if ((raopt = ra_str2opt(optarg)) != NULL) { 501*3048Samaguire /* Set current value appropriately */ 502*3048Samaguire switch (opt) { 503*3048Samaguire case 'd': 504*3048Samaguire raopt->opt_enabled = B_FALSE; 505*3048Samaguire break; 506*3048Samaguire case 'e': 507*3048Samaguire /* 508*3048Samaguire * Check legacy daemons, mark 509*3048Samaguire * routing-svcs. 510*3048Samaguire */ 511*3048Samaguire if (IS_ROUTING_OPT(optarg) && 512*3048Samaguire ra_check_legacy_daemons() == -1) 513*3048Samaguire exit(EXIT_FAILURE); 514*3048Samaguire raopt->opt_enabled = B_TRUE; 515*3048Samaguire break; 516*3048Samaguire case 'r': 517*3048Samaguire /* 518*3048Samaguire * This callback sets opt_enabled to 519*3048Samaguire * the default value. 520*3048Samaguire */ 521*3048Samaguire ra_resetopts(); 522*3048Samaguire if (ra_smf_cb(ra_get_default_opt_cb, 523*3048Samaguire raopt->opt_default_fmri, raopt) 524*3048Samaguire == -1) 525*3048Samaguire exit(EXIT_FAILURE); 526*3048Samaguire if (raopt->opt_enabled && 527*3048Samaguire IS_ROUTING_OPT(optarg) && 528*3048Samaguire ra_check_legacy_daemons() == -1) 529*3048Samaguire exit(EXIT_FAILURE); 530*3048Samaguire /* set value to default */ 531*3048Samaguire raopt->opt_enabled = 532*3048Samaguire raopt->opt_default_enabled; 533*3048Samaguire break; 534*3048Samaguire } 535*3048Samaguire if (ra_smf_cb(ra_set_persistent_opt_cb, 536*3048Samaguire raopt->opt_fmri, raopt) == -1) 537*3048Samaguire exit(EXIT_FAILURE); 538*3048Samaguire } else if ((ravar = ra_str2var(optarg)) != NULL) { 539*3048Samaguire if (opt != 'r') { 540*3048Samaguire usage(); 541*3048Samaguire exit(EXIT_FAILURE); 542*3048Samaguire } 543*3048Samaguire /* set current value to default */ 544*3048Samaguire ra_resetopts(); 545*3048Samaguire if (ra_smf_cb(ra_get_default_var_cb, 546*3048Samaguire ravar->var_default_fmri, ravar) == -1) 547*3048Samaguire exit(EXIT_FAILURE); 548*3048Samaguire /* Need special case for routing-svcs var */ 549*3048Samaguire if (strcmp(ravar->var_name, RA_VAR_ROUTING_SVCS) 550*3048Samaguire == 0) { 551*3048Samaguire if (ra_update_routing_svcs( 552*3048Samaguire ravar->var_default_value) == -1) 553*3048Samaguire exit(EXIT_FAILURE); 554*3048Samaguire } else if (ra_smf_cb(ra_set_persistent_var_cb, 555*3048Samaguire ravar->var_fmri, ravar) == -1) 556*3048Samaguire exit(EXIT_FAILURE); 557*3048Samaguire } else { 558*3048Samaguire (void) fprintf(stderr, gettext( 559*3048Samaguire "%1$s: invalid option: %2$s\n"), myname, 560*3048Samaguire optarg); 561*3048Samaguire usage(); 562*3048Samaguire exit(EXIT_FAILURE); 563*3048Samaguire } 564*3048Samaguire modify = B_TRUE; 565*3048Samaguire break; 566*3048Samaguire case 'l': 567*3048Samaguire if (ra_smf_cb(ra_list_props_cb, optarg, NULL) == -1) 568*3048Samaguire exit(EXIT_FAILURE); 569*3048Samaguire report = B_FALSE; 570*3048Samaguire break; 571*3048Samaguire case 'm': 572*3048Samaguire fmri = optarg; 573*3048Samaguire modify = B_TRUE; 574*3048Samaguire /* 575*3048Samaguire * Argument list of key=value pairs, we need to 576*3048Samaguire * collate all matching keys to set multiple values. 577*3048Samaguire */ 578*3048Samaguire numargs = 1; 579*3048Samaguire i = optind; 580*3048Samaguire for (numargs = 1; argv[i] != NULL && argv[i][0] != '-'; 581*3048Samaguire numargs++) 582*3048Samaguire i++; 583*3048Samaguire if (numargs == 1) { 584*3048Samaguire (void) fprintf(stderr, gettext( 585*3048Samaguire "%s: key=value required for " 586*3048Samaguire "property change\n"), myname); 587*3048Samaguire usage(); 588*3048Samaguire exit(EXIT_FAILURE); 589*3048Samaguire } 590*3048Samaguire if (alt_root_set) { 591*3048Samaguire if (ra_upgrade_cmd(opt, numargs, 592*3048Samaguire &argv[optind - 1]) == -1) 593*3048Samaguire exit(EXIT_FAILURE); 594*3048Samaguire optind += numargs - 1; 595*3048Samaguire break; 596*3048Samaguire } 597*3048Samaguire /* 598*3048Samaguire * Collect all key=value pairs which use same key 599*3048Samaguire * so we can add multiple property values. 600*3048Samaguire */ 601*3048Samaguire for (key = argv[optind]; key != NULL && key[0] != '-'; 602*3048Samaguire key = argv[++optind]) { 603*3048Samaguire if (key[0] == '\0') 604*3048Samaguire continue; 605*3048Samaguire vals = malloc(sizeof (char *)); 606*3048Samaguire if ((vals[0] = strchr(key, '=')) == NULL) { 607*3048Samaguire (void) fprintf(stderr, gettext( 608*3048Samaguire "%s: Malformed name=value " 609*3048Samaguire "pair %s\n"), myname, key); 610*3048Samaguire exit(EXIT_FAILURE); 611*3048Samaguire } 612*3048Samaguire numvalues = 1; 613*3048Samaguire *(vals[0]) = '\0'; 614*3048Samaguire (vals[0])++; 615*3048Samaguire i = optind + 1; 616*3048Samaguire for (nk = argv[i]; 617*3048Samaguire nk != NULL && nk[0] != '-'; 618*3048Samaguire nk = argv[++i]) { 619*3048Samaguire if (nk[0] == '\0') 620*3048Samaguire continue; 621*3048Samaguire if ((keyend = strchr(nk, '=')) 622*3048Samaguire == NULL) { 623*3048Samaguire (void) fprintf(stderr, gettext( 624*3048Samaguire "%s: Malformed name=value " 625*3048Samaguire " pair %s\n"), myname, nk); 626*3048Samaguire exit(EXIT_FAILURE); 627*3048Samaguire } 628*3048Samaguire if ((keylen = keyend - nk) != 629*3048Samaguire strlen(key)) 630*3048Samaguire continue; 631*3048Samaguire if (strncmp(key, nk, keylen) == 0) { 632*3048Samaguire vals = realloc(vals, ++numvalues 633*3048Samaguire * sizeof (char *)); 634*3048Samaguire vals[numvalues - 1] = ++keyend; 635*3048Samaguire nk[0] = '\0'; 636*3048Samaguire optind++; 637*3048Samaguire } 638*3048Samaguire } 639*3048Samaguire raprop.prop_name = key; 640*3048Samaguire raprop.prop_values = vals; 641*3048Samaguire raprop.prop_numvalues = numvalues; 642*3048Samaguire if (ra_smf_cb(ra_modify_props_cb, fmri, 643*3048Samaguire &raprop) == -1) 644*3048Samaguire exit(EXIT_FAILURE); 645*3048Samaguire } 646*3048Samaguire break; 647*3048Samaguire case 'p': 648*3048Samaguire parseable = B_TRUE; 649*3048Samaguire parseopt = optarg; 650*3048Samaguire break; 651*3048Samaguire case 'R': 652*3048Samaguire if (chroot(optarg) == -1) { 653*3048Samaguire (void) fprintf(stderr, gettext( 654*3048Samaguire "%1$s: failed to chroot to %2$s: %3$s\n"), 655*3048Samaguire myname, optarg, strerror(errno)); 656*3048Samaguire exit(EXIT_FAILURE); 657*3048Samaguire } 658*3048Samaguire alt_root_set = B_TRUE; 659*3048Samaguire report = B_FALSE; 660*3048Samaguire break; 661*3048Samaguire case 's': 662*3048Samaguire if (alt_root_set) { 663*3048Samaguire if (ra_upgrade_cmd(opt, 1, &optarg) == -1) 664*3048Samaguire exit(EXIT_FAILURE); 665*3048Samaguire modify = B_TRUE; 666*3048Samaguire break; 667*3048Samaguire } 668*3048Samaguire options = optarg; 669*3048Samaguire while (*options != '\0') { 670*3048Samaguire opt_index = getsubopt(&options, v_opt, &val); 671*3048Samaguire if (val == NULL) { 672*3048Samaguire usage(); 673*3048Samaguire exit(EXIT_FAILURE); 674*3048Samaguire } 675*3048Samaguire if (opt_index == -1) { 676*3048Samaguire (void) fprintf(stderr, gettext( 677*3048Samaguire "%1$s: invalid variable: %2$s\n"), 678*3048Samaguire myname, optarg); 679*3048Samaguire usage(); 680*3048Samaguire exit(EXIT_FAILURE); 681*3048Samaguire } 682*3048Samaguire ravar = &ra_vars[opt_index]; 683*3048Samaguire /* Need special case for routing-svcs var */ 684*3048Samaguire if (strcmp(ravar->var_name, RA_VAR_ROUTING_SVCS) 685*3048Samaguire == 0) { 686*3048Samaguire if (ra_update_routing_svcs(val) == -1) 687*3048Samaguire return (-1); 688*3048Samaguire } else { 689*3048Samaguire ravar->var_value = strdup(val); 690*3048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb, 691*3048Samaguire ravar->var_fmri, ravar) == -1) 692*3048Samaguire exit(EXIT_FAILURE); 693*3048Samaguire } 694*3048Samaguire } 695*3048Samaguire modify = B_TRUE; 696*3048Samaguire break; 697*3048Samaguire case 'u': 698*3048Samaguire update = B_TRUE; 699*3048Samaguire break; 700*3048Samaguire case ':': 701*3048Samaguire /* if not 'p', usage failure */ 702*3048Samaguire if (strcmp(argv[optind - 1], "-p") != 0) { 703*3048Samaguire (void) fprintf(stderr, gettext( 704*3048Samaguire "%s: option requires an argument -%s\n"), 705*3048Samaguire myname, argv[optind - 1]); 706*3048Samaguire usage(); 707*3048Samaguire exit(EXIT_FAILURE); 708*3048Samaguire } 709*3048Samaguire parseable = B_TRUE; 710*3048Samaguire break; 711*3048Samaguire case '?': 712*3048Samaguire usage(); 713*3048Samaguire exit(EXIT_FAILURE); 714*3048Samaguire } 715*3048Samaguire } 716*3048Samaguire 717*3048Samaguire if (argc > optind) { 718*3048Samaguire /* There shouldn't be any extra args. */ 719*3048Samaguire usage(); 720*3048Samaguire exit(EXIT_FAILURE); 721*3048Samaguire } 722*3048Samaguire 723*3048Samaguire if (parseable && (update || modify)) { 724*3048Samaguire (void) fprintf(stderr, gettext("%s: the -p option cannot be " 725*3048Samaguire "used with any of -demrsu\n"), myname); 726*3048Samaguire usage(); 727*3048Samaguire exit(EXIT_FAILURE); 728*3048Samaguire } 729*3048Samaguire 730*3048Samaguire if (update && ! alt_root_set) 731*3048Samaguire status = ra_update(); 732*3048Samaguire 733*3048Samaguire if (report && !modify && !update) 734*3048Samaguire status = ra_report(parseable, parseopt); 735*3048Samaguire 736*3048Samaguire return (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 737*3048Samaguire } 738*3048Samaguire 739*3048Samaguire /* 740*3048Samaguire * Upgrade legacy daemons, mark to-be-enabled routing services. 741*3048Samaguire */ 742*3048Samaguire static int 743*3048Samaguire ra_check_legacy_daemons(void) 744*3048Samaguire { 745*3048Samaguire ravar_t *routing_svcs = ra_str2var(RA_VAR_ROUTING_SVCS); 746*3048Samaguire ravar_t *v4d = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON); 747*3048Samaguire ravar_t *v6d = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON); 748*3048Samaguire char *fmri, *nextfmri; 749*3048Samaguire boolean_t mark = B_FALSE; 750*3048Samaguire 751*3048Samaguire if (ra_smf_cb(ra_get_persistent_var_cb, routing_svcs->var_fmri, 752*3048Samaguire routing_svcs) == -1) 753*3048Samaguire return (-1); 754*3048Samaguire 755*3048Samaguire /* First unmark all services */ 756*3048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, NULL, &mark) == -1) 757*3048Samaguire return (-1); 758*3048Samaguire 759*3048Samaguire mark = B_TRUE; 760*3048Samaguire if (routing_svcs->var_value != NULL) { 761*3048Samaguire /* 762*3048Samaguire * For routing-svcs variable, mark each named 763*3048Samaguire * service as a current-routing-svc. 764*3048Samaguire */ 765*3048Samaguire if ((fmri = strdup(routing_svcs->var_value)) == NULL) { 766*3048Samaguire (void) fprintf(stderr, gettext( 767*3048Samaguire "%s: out of memory\n"), myname); 768*3048Samaguire return (-1); 769*3048Samaguire } 770*3048Samaguire /* Now, mark each service named in routing-svcs. */ 771*3048Samaguire for (nextfmri = strtok(fmri, " \t"); 772*3048Samaguire nextfmri != NULL; 773*3048Samaguire nextfmri = strtok(NULL, " \t")) { 774*3048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, nextfmri, 775*3048Samaguire &mark) == -1) { 776*3048Samaguire free(fmri); 777*3048Samaguire return (-1); 778*3048Samaguire } 779*3048Samaguire } 780*3048Samaguire free(fmri); 781*3048Samaguire } 782*3048Samaguire 783*3048Samaguire /* 784*3048Samaguire * Now check if legacy variables (if specified) map to SMF routing 785*3048Samaguire * daemons. If so, transfer associated daemon arguments. 786*3048Samaguire */ 787*3048Samaguire if (ra_upgrade_legacy_daemons() == -1) 788*3048Samaguire return (-1); 789*3048Samaguire 790*3048Samaguire ra_resetvars(NULL); 791*3048Samaguire /* 792*3048Samaguire * At this point, if the legacy services still have ipv4/ipv6 793*3048Samaguire * routing daemons specified, we know they weren`t upgraded, so 794*3048Samaguire * we mark them also. 795*3048Samaguire */ 796*3048Samaguire if (ra_smf_cb(ra_get_persistent_var_cb, v4d->var_fmri, v4d) == -1 || 797*3048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v6d->var_fmri, v6d) == -1) 798*3048Samaguire return (-1); 799*3048Samaguire 800*3048Samaguire if (v4d->var_value != NULL && strtok(v4d->var_value, " \t") != NULL && 801*3048Samaguire ra_smf_cb(ra_mark_routing_svcs_cb, RA_INSTANCE_LEGACY_ROUTING_IPV4, 802*3048Samaguire &mark) == -1) 803*3048Samaguire return (-1); 804*3048Samaguire if (v6d->var_value != NULL && strtok(v6d->var_value, " \t") != NULL && 805*3048Samaguire ra_smf_cb(ra_mark_routing_svcs_cb, RA_INSTANCE_LEGACY_ROUTING_IPV6, 806*3048Samaguire &mark) == -1) 807*3048Samaguire return (-1); 808*3048Samaguire 809*3048Samaguire return (0); 810*3048Samaguire } 811*3048Samaguire 812*3048Samaguire /* 813*3048Samaguire * Retrieve legacy daemon variables, and check if any SMF routing daemons 814*3048Samaguire * run the daemons specified. If so, the legacy configuration (arguments 815*3048Samaguire * to the daemon) is transferred to the routeadm/daemon-args property 816*3048Samaguire * of the corresponding instance. From there, the instance picks up the 817*3048Samaguire * value and will transfer the daemon arguments to individiual properties 818*3048Samaguire * when enabled. 819*3048Samaguire */ 820*3048Samaguire static int 821*3048Samaguire ra_upgrade_legacy_daemons(void) 822*3048Samaguire { 823*3048Samaguire ravar_t *v4d = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON); 824*3048Samaguire ravar_t *v6d = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON); 825*3048Samaguire ravar_t *v4args = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON_ARGS); 826*3048Samaguire ravar_t *v6args = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON_ARGS); 827*3048Samaguire ravar_t *v4stop = ra_str2var(RA_VAR_IPV4_ROUTING_STOP_CMD); 828*3048Samaguire ravar_t *v6stop = ra_str2var(RA_VAR_IPV6_ROUTING_STOP_CMD); 829*3048Samaguire 830*3048Samaguire if (ra_smf_cb(ra_get_persistent_var_cb, v4d->var_fmri, v4d) == -1 || 831*3048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v6d->var_fmri, v6d) == -1 || 832*3048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v4args->var_fmri, v4args) 833*3048Samaguire == -1 || 834*3048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v6args->var_fmri, v6args) 835*3048Samaguire == -1 || 836*3048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v4stop->var_fmri, v4stop) 837*3048Samaguire == -1 || 838*3048Samaguire ra_smf_cb(ra_get_persistent_var_cb, v6stop->var_fmri, v6stop) 839*3048Samaguire == -1) 840*3048Samaguire return (-1); 841*3048Samaguire 842*3048Samaguire return (ra_smf_cb(ra_upgrade_legacy_daemons_cb, NULL, NULL)); 843*3048Samaguire } 844*3048Samaguire 845*3048Samaguire /* 846*3048Samaguire * Determine if service runs the same daemon as that which is specified 847*3048Samaguire * in ipv4-routing-daemon or ipv6-routing-daemon. If so, the associated 848*3048Samaguire * daemon arguments are transferred to the service. 849*3048Samaguire */ 850*3048Samaguire 851*3048Samaguire /* ARGSUSED0 */ 852*3048Samaguire static int 853*3048Samaguire ra_upgrade_legacy_daemons_cb(void *data, scf_walkinfo_t *wip) 854*3048Samaguire { 855*3048Samaguire const char *inst_fmri = wip->fmri; 856*3048Samaguire scf_instance_t *inst = wip->inst; 857*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 858*3048Samaguire char *daemon, *l_daemon = NULL; 859*3048Samaguire ravar_t *v4d = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON); 860*3048Samaguire ravar_t *v6d = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON); 861*3048Samaguire ravar_t *v4args = ra_str2var(RA_VAR_IPV4_ROUTING_DAEMON_ARGS); 862*3048Samaguire ravar_t *v6args = ra_str2var(RA_VAR_IPV6_ROUTING_DAEMON_ARGS); 863*3048Samaguire ravar_t *v4stop = ra_str2var(RA_VAR_IPV4_ROUTING_STOP_CMD); 864*3048Samaguire ravar_t *v6stop = ra_str2var(RA_VAR_IPV6_ROUTING_STOP_CMD); 865*3048Samaguire ravar_t *routing_svcs = ra_str2var(RA_VAR_ROUTING_SVCS); 866*3048Samaguire boolean_t mark, marked; 867*3048Samaguire char *new_routing_svcs; 868*3048Samaguire 869*3048Samaguire /* 870*3048Samaguire * Ensure instance is a routing service, and not one of the 871*3048Samaguire * legacy instances - if it is, the daemon property is already 872*3048Samaguire * set to the legacy daemon. 873*3048Samaguire */ 874*3048Samaguire if (ra_get_single_prop_as_string(h, inst, RA_PG_ROUTEADM, 875*3048Samaguire RA_PROP_DAEMON, B_TRUE, B_FALSE, NULL, &daemon) == -1 || 876*3048Samaguire strcmp(RA_INSTANCE_LEGACY_ROUTING_IPV4, inst_fmri) == 0 || 877*3048Samaguire strcmp(RA_INSTANCE_LEGACY_ROUTING_IPV6, inst_fmri) == 0) 878*3048Samaguire return (0); 879*3048Samaguire 880*3048Samaguire /* A legacy daemon may be defined */ 881*3048Samaguire (void) ra_get_single_prop_as_string(h, inst, RA_PG_ROUTEADM, 882*3048Samaguire RA_PROP_LEGACY_DAEMON, B_TRUE, B_FALSE, NULL, &l_daemon); 883*3048Samaguire 884*3048Samaguire /* 885*3048Samaguire * If we match daemon/legacy_daemon with ipv4-routing-daemon or 886*3048Samaguire * ipv6-routing-daemon values, transfer daemon-args value 887*3048Samaguire * to the matching service. 888*3048Samaguire */ 889*3048Samaguire if (v4d->var_value != NULL && (strcmp(v4d->var_value, daemon) == 0 || 890*3048Samaguire (l_daemon != NULL && strcmp(v4d->var_value, l_daemon) == 0))) { 891*3048Samaguire (void) printf(gettext("%s: migrating daemon configuration " 892*3048Samaguire "for %s to %s\n"), myname, l_daemon != NULL ? 893*3048Samaguire l_daemon : daemon, inst_fmri); 894*3048Samaguire /* Transfer daemon-args value, clear legacy v4 values */ 895*3048Samaguire if (ra_set_prop_from_string(h, inst, RA_PG_ROUTEADM, 896*3048Samaguire RA_PROP_DAEMON_ARGS, SCF_TYPE_ASTRING, B_TRUE, 1, 897*3048Samaguire (const char **)&(v4args->var_value)) == -1) 898*3048Samaguire return (-1); 899*3048Samaguire ra_resetvars(RA_PROPVAL_PROTO_IPV4); 900*3048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb, 901*3048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV4, v4d) == -1 || 902*3048Samaguire ra_smf_cb(ra_set_persistent_var_cb, 903*3048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV4, v4args) == -1 || 904*3048Samaguire ra_smf_cb(ra_set_persistent_var_cb, 905*3048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV4, v4stop) == -1) 906*3048Samaguire return (-1); 907*3048Samaguire } else if (v6d->var_value != NULL && (strcmp(v6d->var_value, daemon) 908*3048Samaguire == 0 || 909*3048Samaguire (l_daemon != NULL && strcmp(v6d->var_value, l_daemon) == 0))) { 910*3048Samaguire (void) printf(gettext("%s: migrating daemon configuration " 911*3048Samaguire "for %s to %s\n"), myname, l_daemon != NULL ? 912*3048Samaguire l_daemon : daemon, inst_fmri); 913*3048Samaguire /* Transfer daemon-args value, clear legacy v6 values */ 914*3048Samaguire if (ra_set_prop_from_string(h, inst, RA_PG_ROUTEADM, 915*3048Samaguire RA_PROP_DAEMON_ARGS, SCF_TYPE_ASTRING, B_TRUE, 1, 916*3048Samaguire (const char **)&(v6args->var_value)) == -1) 917*3048Samaguire return (-1); 918*3048Samaguire ra_resetvars(RA_PROPVAL_PROTO_IPV6); 919*3048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb, 920*3048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV6, v6d) == -1 || 921*3048Samaguire ra_smf_cb(ra_set_persistent_var_cb, 922*3048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV6, v6args) == -1 || 923*3048Samaguire ra_smf_cb(ra_set_persistent_var_cb, 924*3048Samaguire RA_INSTANCE_LEGACY_ROUTING_IPV6, v6stop) == -1) 925*3048Samaguire return (-1); 926*3048Samaguire } else 927*3048Samaguire return (0); 928*3048Samaguire 929*3048Samaguire /* 930*3048Samaguire * If service is unmarked at this point, add it to routing-svcs and 931*3048Samaguire * mark it. 932*3048Samaguire */ 933*3048Samaguire if (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM, 934*3048Samaguire RA_PROP_CURR_ROUTING_SVC, B_FALSE, B_FALSE, &marked) == -1 || 935*3048Samaguire marked == B_FALSE) { 936*3048Samaguire mark = B_TRUE; 937*3048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, inst_fmri, &mark) 938*3048Samaguire == -1 || 939*3048Samaguire ra_smf_cb(ra_get_persistent_var_cb, routing_svcs->var_fmri, 940*3048Samaguire routing_svcs) == -1) 941*3048Samaguire return (-1); 942*3048Samaguire if ((new_routing_svcs = 943*3048Samaguire malloc(strlen(routing_svcs->var_value) + 944*3048Samaguire strlen(inst_fmri) + 2)) == NULL) { 945*3048Samaguire (void) fprintf(stderr, gettext( 946*3048Samaguire "%s: out of memory"), myname); 947*3048Samaguire return (-1); 948*3048Samaguire } 949*3048Samaguire if (strlen(routing_svcs->var_value) == 0) 950*3048Samaguire (void) snprintf(new_routing_svcs, 951*3048Samaguire strlen(inst_fmri) + 1, "%s", inst_fmri); 952*3048Samaguire else 953*3048Samaguire (void) snprintf(new_routing_svcs, 954*3048Samaguire strlen(routing_svcs->var_value) + 955*3048Samaguire strlen(inst_fmri) + 2, "%s %s", 956*3048Samaguire routing_svcs->var_value, inst_fmri); 957*3048Samaguire free(routing_svcs->var_value); 958*3048Samaguire routing_svcs->var_value = new_routing_svcs; 959*3048Samaguire (void) smf_refresh_instance(inst_fmri); 960*3048Samaguire return (ra_smf_cb(ra_set_persistent_var_cb, 961*3048Samaguire routing_svcs->var_fmri, routing_svcs)); 962*3048Samaguire } 963*3048Samaguire (void) smf_refresh_instance(inst_fmri); 964*3048Samaguire return (0); 965*3048Samaguire } 966*3048Samaguire 967*3048Samaguire /* 968*3048Samaguire * If we are upgrading, append operation to <alt_root>/var/svc/profile/upgrade. 969*3048Samaguire */ 970*3048Samaguire static int 971*3048Samaguire ra_upgrade_cmd(char opt, int argc, char **argv) 972*3048Samaguire { 973*3048Samaguire FILE *fp; 974*3048Samaguire int i; 975*3048Samaguire 976*3048Samaguire if ((fp = fopen(RA_SMF_UPGRADE_FILE, "a+")) == NULL) { 977*3048Samaguire (void) fprintf(stderr, gettext( 978*3048Samaguire "%1$s: failed to open %2$s: %3$s\n"), 979*3048Samaguire myname, RA_SMF_UPGRADE_FILE, strerror(errno)); 980*3048Samaguire return (-1); 981*3048Samaguire } 982*3048Samaguire (void) fprintf(fp, "/sbin/routeadm -%c ", opt); 983*3048Samaguire if (argv != NULL) { 984*3048Samaguire for (i = 0; i < argc; i++) 985*3048Samaguire (void) fprintf(fp, "%s ", argv[i]); 986*3048Samaguire } 987*3048Samaguire (void) fprintf(fp, "%s\n", RA_SMF_UPGRADE_MSG); 988*3048Samaguire (void) fclose(fp); 989*3048Samaguire return (0); 990*3048Samaguire } 991*3048Samaguire 992*3048Samaguire /* 993*3048Samaguire * Set current state to "next boot" state, i.e. if general/enabled 994*3048Samaguire * value is overlaid by a general_ovr/enabled value, set the current state 995*3048Samaguire * to the value of the latter. Doing this applies "next boot" changes to 996*3048Samaguire * the current setup. 997*3048Samaguire */ 998*3048Samaguire static int 999*3048Samaguire ra_update(void) 1000*3048Samaguire { 1001*3048Samaguire int i, ret = 0; 1002*3048Samaguire 1003*3048Samaguire if (ra_check_legacy_daemons() == -1) 1004*3048Samaguire return (-1); 1005*3048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) { 1006*3048Samaguire if ((ret = ra_smf_cb(ra_set_current_opt_cb, ra_opts[i].opt_fmri, 1007*3048Samaguire &ra_opts[i])) == -1) 1008*3048Samaguire break; 1009*3048Samaguire } 1010*3048Samaguire return (ret); 1011*3048Samaguire } 1012*3048Samaguire 1013*3048Samaguire /* 1014*3048Samaguire * Here we catch the special case where ipv4/ipv6 routing was enabled, 1015*3048Samaguire * and the user updates the routing-svcs list. The problem is that 1016*3048Samaguire * the enabled state is the result of services on the old routing-svcs list 1017*3048Samaguire * being enabled, and we want to support users doing something like this: 1018*3048Samaguire * 1019*3048Samaguire * # routeadm -s routing-svcs=route -e ipv4-routing -u 1020*3048Samaguire * 1021*3048Samaguire * followed by 1022*3048Samaguire * 1023*3048Samaguire * # routeadm -s routing-svcs=rdisc -u 1024*3048Samaguire * 1025*3048Samaguire * To do this, we need to: 1026*3048Samaguire * - cache the old ipv4-routing/ipv6-routing values. 1027*3048Samaguire * - persistently disable the old routing-svcs list. 1028*3048Samaguire * - if ipv4-routing was enabled, mark and persistently enable all the new 1029*3048Samaguire * v4 routing-svcs 1030*3048Samaguire * - if ipv6-routing was enabled, mark and persistently enable all the new 1031*3048Samaguire * v6 routing-svcs. 1032*3048Samaguire * This will result in the next "-u" switching on the new routing-svcs, and 1033*3048Samaguire * switching off the old ones, as the user would expect. 1034*3048Samaguire */ 1035*3048Samaguire static int 1036*3048Samaguire ra_update_routing_svcs(char *routing_svcs_new) 1037*3048Samaguire { 1038*3048Samaguire raopt_t *v4opt = ra_str2opt(RA_OPT_IPV4_ROUTING); 1039*3048Samaguire raopt_t *v6opt = ra_str2opt(RA_OPT_IPV6_ROUTING); 1040*3048Samaguire ravar_t *routing_svcs = ra_str2var(RA_VAR_ROUTING_SVCS); 1041*3048Samaguire char *routing_svcs_old, *fmri; 1042*3048Samaguire boolean_t v4_old, v6_old, mark = B_FALSE; 1043*3048Samaguire 1044*3048Samaguire ra_resetopts(); 1045*3048Samaguire if (ra_smf_cb(ra_get_persistent_opt_cb, v4opt->opt_fmri, v4opt) == -1 || 1046*3048Samaguire ra_smf_cb(ra_get_persistent_opt_cb, v6opt->opt_fmri, v6opt) == -1 || 1047*3048Samaguire ra_smf_cb(ra_get_persistent_var_cb, routing_svcs->var_fmri, 1048*3048Samaguire routing_svcs) == -1) 1049*3048Samaguire return (-1); 1050*3048Samaguire v4_old = v4opt->opt_enabled; 1051*3048Samaguire v6_old = v6opt->opt_enabled; 1052*3048Samaguire routing_svcs_old = routing_svcs->var_value; 1053*3048Samaguire routing_svcs->var_value = routing_svcs_new; 1054*3048Samaguire 1055*3048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb, routing_svcs->var_fmri, 1056*3048Samaguire routing_svcs) == -1) { 1057*3048Samaguire free(routing_svcs_old); 1058*3048Samaguire return (-1); 1059*3048Samaguire } 1060*3048Samaguire 1061*3048Samaguire if (!v4_old && !v6_old) { 1062*3048Samaguire /* We don`t need to do anything, since services were disabled */ 1063*3048Samaguire free(routing_svcs_old); 1064*3048Samaguire return (0); 1065*3048Samaguire } 1066*3048Samaguire v4opt->opt_enabled = B_FALSE; 1067*3048Samaguire v6opt->opt_enabled = B_FALSE; 1068*3048Samaguire 1069*3048Samaguire /* Persistently disable each old v4/v6 "routing-svc" */ 1070*3048Samaguire for (fmri = strtok(routing_svcs_old, " \t"); fmri != NULL; 1071*3048Samaguire fmri = strtok(NULL, " \t")) { 1072*3048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, fmri, &mark) == -1) { 1073*3048Samaguire free(routing_svcs_old); 1074*3048Samaguire return (-1); 1075*3048Samaguire } 1076*3048Samaguire if (v4_old && 1077*3048Samaguire ra_smf_cb(ra_set_persistent_opt_cb, fmri, v4opt) == -1) { 1078*3048Samaguire free(routing_svcs_old); 1079*3048Samaguire return (-1); 1080*3048Samaguire } 1081*3048Samaguire if (v6_old && 1082*3048Samaguire ra_smf_cb(ra_set_persistent_opt_cb, fmri, v6opt) == -1) { 1083*3048Samaguire free(routing_svcs_old); 1084*3048Samaguire return (-1); 1085*3048Samaguire } 1086*3048Samaguire } 1087*3048Samaguire free(routing_svcs_old); 1088*3048Samaguire v4opt->opt_enabled = v4_old; 1089*3048Samaguire v6opt->opt_enabled = v6_old; 1090*3048Samaguire 1091*3048Samaguire /* Persistently enable each new v4/v6 "routing-svc" */ 1092*3048Samaguire mark = B_TRUE; 1093*3048Samaguire for (fmri = strtok(routing_svcs_new, " \t"); fmri != NULL; 1094*3048Samaguire fmri = strtok(NULL, " \t")) { 1095*3048Samaguire if (ra_smf_cb(ra_mark_routing_svcs_cb, fmri, &mark) == -1) 1096*3048Samaguire return (-1); 1097*3048Samaguire if (v4_old && 1098*3048Samaguire ra_smf_cb(ra_set_persistent_opt_cb, fmri, v4opt) == -1) 1099*3048Samaguire return (-1); 1100*3048Samaguire if (v6_old && 1101*3048Samaguire ra_smf_cb(ra_set_persistent_opt_cb, fmri, v6opt) == -1) 1102*3048Samaguire return (-1); 1103*3048Samaguire } 1104*3048Samaguire return (0); 1105*3048Samaguire } 1106*3048Samaguire 1107*3048Samaguire /* 1108*3048Samaguire * Display status, in parseable form if required. If param is 1109*3048Samaguire * specified, only the named option/variable is displayed (this option is 1110*3048Samaguire * for parseable display only). 1111*3048Samaguire */ 1112*3048Samaguire static int 1113*3048Samaguire ra_report(boolean_t parseable, const char *param) 1114*3048Samaguire { 1115*3048Samaguire int i; 1116*3048Samaguire char *c_state, *d_state, *p_state, *p_var, *d_var; 1117*3048Samaguire char *enabled = "enabled"; 1118*3048Samaguire char *disabled = "disabled"; 1119*3048Samaguire boolean_t param_found = B_FALSE; 1120*3048Samaguire 1121*3048Samaguire if (!parseable) { 1122*3048Samaguire (void) printf(gettext( 1123*3048Samaguire " Configuration Current " 1124*3048Samaguire "Current\n" 1125*3048Samaguire " Option Configuration " 1126*3048Samaguire "System State\n" 1127*3048Samaguire "---------------------------------------------------" 1128*3048Samaguire "------------\n")); 1129*3048Samaguire } 1130*3048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) { 1131*3048Samaguire if (param != NULL) { 1132*3048Samaguire if (strcmp(ra_opts[i].opt_name, param) == 0) 1133*3048Samaguire param_found = B_TRUE; 1134*3048Samaguire else 1135*3048Samaguire continue; 1136*3048Samaguire } 1137*3048Samaguire if (ra_smf_cb(ra_get_current_opt_cb, 1138*3048Samaguire ra_opts[i].opt_fmri, &ra_opts[i]) == -1) 1139*3048Samaguire return (-1); 1140*3048Samaguire c_state = ra_opts[i].opt_enabled ? enabled : disabled; 1141*3048Samaguire ra_resetopts(); 1142*3048Samaguire if (ra_smf_cb(ra_get_persistent_opt_cb, 1143*3048Samaguire ra_opts[i].opt_fmri, &ra_opts[i]) == -1) 1144*3048Samaguire return (-1); 1145*3048Samaguire p_state = ra_opts[i].opt_enabled ? enabled : disabled; 1146*3048Samaguire ra_resetopts(); 1147*3048Samaguire if (ra_smf_cb(ra_get_default_opt_cb, 1148*3048Samaguire ra_opts[i].opt_default_fmri, &ra_opts[i]) == -1) 1149*3048Samaguire return (-1); 1150*3048Samaguire d_state = ra_opts[i].opt_default_enabled ? enabled : disabled; 1151*3048Samaguire ra_resetopts(); 1152*3048Samaguire if (parseable) { 1153*3048Samaguire if (param == NULL) 1154*3048Samaguire (void) printf("%s ", ra_opts[i].opt_name); 1155*3048Samaguire (void) printf("persistent=%s default=%s " 1156*3048Samaguire "current=%s\n", p_state, d_state, c_state); 1157*3048Samaguire } else { 1158*3048Samaguire (void) printf(gettext("%1$27s %2$-21s%3$s\n"), 1159*3048Samaguire ra_intloptname(ra_opts[i].opt_name), 1160*3048Samaguire p_state, c_state); 1161*3048Samaguire } 1162*3048Samaguire } 1163*3048Samaguire if (!parseable) 1164*3048Samaguire (void) printf("\n"); 1165*3048Samaguire 1166*3048Samaguire ra_resetvars(NULL); 1167*3048Samaguire 1168*3048Samaguire /* Gather persistent/default variable values */ 1169*3048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) { 1170*3048Samaguire if (ra_smf_cb(ra_get_persistent_var_cb, 1171*3048Samaguire ra_vars[i].var_fmri, &ra_vars[i]) == -1 || 1172*3048Samaguire ra_smf_cb(ra_get_default_var_cb, 1173*3048Samaguire ra_vars[i].var_default_fmri, &ra_vars[i]) == -1) 1174*3048Samaguire return (-1); 1175*3048Samaguire 1176*3048Samaguire } 1177*3048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) { 1178*3048Samaguire if (param != NULL) { 1179*3048Samaguire if (strcmp(ra_vars[i].var_name, param) == 0) 1180*3048Samaguire param_found = B_TRUE; 1181*3048Samaguire else 1182*3048Samaguire continue; 1183*3048Samaguire } 1184*3048Samaguire p_var = ra_vars[i].var_value == NULL ? "": 1185*3048Samaguire ra_vars[i].var_value; 1186*3048Samaguire d_var = ra_vars[i].var_default_value == NULL ? 1187*3048Samaguire "": ra_vars[i].var_default_value; 1188*3048Samaguire if (parseable) { 1189*3048Samaguire if (param == NULL) 1190*3048Samaguire (void) printf("%s ", ra_vars[i].var_name); 1191*3048Samaguire (void) printf("persistent=\"%s\" " 1192*3048Samaguire "default=\"%s\" \n", p_var, d_var); 1193*3048Samaguire } else { 1194*3048Samaguire /* If daemon variables are not set, do not display. */ 1195*3048Samaguire if ((IS_IPV4_VAR(ra_vars[i].var_name) && 1196*3048Samaguire IPV4_VARS_UNSET) || 1197*3048Samaguire (IS_IPV6_VAR(ra_vars[i].var_name) && 1198*3048Samaguire IPV6_VARS_UNSET)) 1199*3048Samaguire continue; 1200*3048Samaguire (void) printf(gettext("%1$27s \"%2$s\"\n"), 1201*3048Samaguire ra_intloptname(ra_vars[i].var_name), p_var); 1202*3048Samaguire } 1203*3048Samaguire } 1204*3048Samaguire 1205*3048Samaguire if (param != NULL && !param_found) { 1206*3048Samaguire (void) fprintf(stderr, gettext( 1207*3048Samaguire "%s: no such option/variable %s\n"), myname, param); 1208*3048Samaguire return (-1); 1209*3048Samaguire } 1210*3048Samaguire if (parseable) 1211*3048Samaguire return (0); 1212*3048Samaguire (void) printf(gettext("\nRouting daemons:\n")); 1213*3048Samaguire (void) printf("\n %s %s\n", "STATE", "FMRI"); 1214*3048Samaguire if (ra_smf_cb(ra_print_state_cb, NULL, NULL) == -1) 1215*3048Samaguire return (-1); 1216*3048Samaguire return (0); 1217*3048Samaguire } 1218*3048Samaguire 1219*3048Samaguire /* 1220*3048Samaguire * Call scf_walk_fmri() with appropriate function, fmri, and data. 1221*3048Samaguire * A NULL fmri causes scf_walk_fmri() to run on all instances. We make 1222*3048Samaguire * use of this many times in applying changes to the routing services. 1223*3048Samaguire */ 1224*3048Samaguire static int 1225*3048Samaguire ra_smf_cb(ra_smf_cb_t cbfunc, const char *fmri, void *data) 1226*3048Samaguire { 1227*3048Samaguire scf_handle_t *h; 1228*3048Samaguire int exit_status = 0; 1229*3048Samaguire 1230*3048Samaguire if ((h = scf_handle_create(SCF_VERSION)) == NULL || 1231*3048Samaguire scf_handle_bind(h) == -1) { 1232*3048Samaguire (void) fprintf(stderr, gettext( 1233*3048Samaguire "%s: cannot connect to SMF repository\n"), myname); 1234*3048Samaguire return (-1); 1235*3048Samaguire } 1236*3048Samaguire return (scf_walk_fmri(h, fmri == NULL ? 0 : 1, 1237*3048Samaguire fmri == NULL ? NULL : (char **)&fmri, 0, 1238*3048Samaguire cbfunc, data, &exit_status, uu_die)); 1239*3048Samaguire } 1240*3048Samaguire 1241*3048Samaguire /* 1242*3048Samaguire * Applies persistent configuration settings to current setup. 1243*3048Samaguire */ 1244*3048Samaguire static int 1245*3048Samaguire ra_set_current_opt_cb(void *data, scf_walkinfo_t *wip) 1246*3048Samaguire { 1247*3048Samaguire return (ra_get_set_opt_common_cb(data, wip, B_FALSE, B_FALSE)); 1248*3048Samaguire } 1249*3048Samaguire 1250*3048Samaguire /* 1251*3048Samaguire * Sets persistent value for option, to be applied on next boot 1252*3048Samaguire * or by "routeadm -u". 1253*3048Samaguire */ 1254*3048Samaguire static int 1255*3048Samaguire ra_set_persistent_opt_cb(void *data, scf_walkinfo_t *wip) 1256*3048Samaguire { 1257*3048Samaguire return (ra_get_set_opt_common_cb(data, wip, B_TRUE, B_FALSE)); 1258*3048Samaguire } 1259*3048Samaguire 1260*3048Samaguire static int 1261*3048Samaguire ra_get_current_opt_cb(void *data, scf_walkinfo_t *wip) 1262*3048Samaguire { 1263*3048Samaguire return (ra_get_set_opt_common_cb(data, wip, B_FALSE, B_TRUE)); 1264*3048Samaguire } 1265*3048Samaguire 1266*3048Samaguire static int 1267*3048Samaguire ra_get_persistent_opt_cb(void *data, scf_walkinfo_t *wip) 1268*3048Samaguire { 1269*3048Samaguire return (ra_get_set_opt_common_cb(data, wip, B_TRUE, B_TRUE)); 1270*3048Samaguire } 1271*3048Samaguire 1272*3048Samaguire /* 1273*3048Samaguire * Shared function that either sets or determines persistent or current 1274*3048Samaguire * state. Setting persistent state (for next boot) involves setting 1275*3048Samaguire * the general_ovr/enabled value to the current service state, and 1276*3048Samaguire * the general/enabled value to the desired (next-boot) state. 1277*3048Samaguire * Setting current state involves removing the temporary state 1278*3048Samaguire * setting so the persistent state has effect. 1279*3048Samaguire * 1280*3048Samaguire * Persistent state is reported as being enabled if any of the 1281*3048Samaguire * candidate services have a general/enabled value set to true, 1282*3048Samaguire * while current state is reported as being enabled if any of the 1283*3048Samaguire * candidate services has a general_ovr/enabled or general/enabled 1284*3048Samaguire * value set to true. 1285*3048Samaguire */ 1286*3048Samaguire static int 1287*3048Samaguire ra_get_set_opt_common_cb(raopt_t *raopt, scf_walkinfo_t *wip, 1288*3048Samaguire boolean_t persistent, boolean_t get) 1289*3048Samaguire { 1290*3048Samaguire const char *inst_fmri = wip->fmri; 1291*3048Samaguire scf_instance_t *inst = wip->inst; 1292*3048Samaguire scf_instance_t *rinst = NULL; 1293*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1294*3048Samaguire scf_propertygroup_t *routeadm_pg; 1295*3048Samaguire boolean_t persistent_state_enabled; 1296*3048Samaguire boolean_t temporary_state_enabled; 1297*3048Samaguire boolean_t current_state_enabled; 1298*3048Samaguire boolean_t curr_svc = B_TRUE; 1299*3048Samaguire boolean_t found_proto; 1300*3048Samaguire char **protolist = NULL; 1301*3048Samaguire int i, ret, numvalues = 0; 1302*3048Samaguire 1303*3048Samaguire /* 1304*3048Samaguire * Ensure we are dealing with a routeadm-managed service. If 1305*3048Samaguire * the FMRI used for walking instances is NULL, it is reasonable 1306*3048Samaguire * that a service not have a routeadm property group as we will 1307*3048Samaguire * check all services in this case. 1308*3048Samaguire */ 1309*3048Samaguire if (ra_get_pg(h, inst, RA_PG_ROUTEADM, B_TRUE, raopt->opt_fmri != NULL, 1310*3048Samaguire &routeadm_pg) == -1) { 1311*3048Samaguire /* Not a routing service, not an error. */ 1312*3048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND && 1313*3048Samaguire raopt->opt_fmri == NULL) 1314*3048Samaguire return (0); 1315*3048Samaguire return (-1); 1316*3048Samaguire } 1317*3048Samaguire scf_pg_destroy(routeadm_pg); 1318*3048Samaguire 1319*3048Samaguire /* Services with no "protocol" property are not routing daemons */ 1320*3048Samaguire if (raopt->opt_fmri == NULL && ra_get_prop_as_string(h, inst, 1321*3048Samaguire RA_PG_ROUTEADM, RA_PROP_PROTO, B_TRUE, B_FALSE, NULL, &numvalues, 1322*3048Samaguire &protolist) == -1) { 1323*3048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) 1324*3048Samaguire return (0); 1325*3048Samaguire return (-1); 1326*3048Samaguire } 1327*3048Samaguire 1328*3048Samaguire /* 1329*3048Samaguire * Skip invalid services based on flag settings. Flags are used when 1330*3048Samaguire * we run callback functions on all instances to identify 1331*3048Samaguire * the correct instances to operate on. 1332*3048Samaguire */ 1333*3048Samaguire if (raopt->opt_flags & RA_SVC_FLAG_IPV4_ROUTING) { 1334*3048Samaguire found_proto = B_FALSE; 1335*3048Samaguire if (protolist != NULL) { 1336*3048Samaguire /* Check if protolist contains "ipv4" */ 1337*3048Samaguire for (i = 0; i < numvalues; i++) { 1338*3048Samaguire if (protolist[i] != NULL && strcmp( 1339*3048Samaguire protolist[i], RA_PROPVAL_PROTO_IPV4) == 0) 1340*3048Samaguire found_proto = B_TRUE; 1341*3048Samaguire } 1342*3048Samaguire } 1343*3048Samaguire /* If not an ipv4 routing service, skip. */ 1344*3048Samaguire if (protolist == NULL || !found_proto) { 1345*3048Samaguire ra_free_prop_values(numvalues, protolist); 1346*3048Samaguire return (0); 1347*3048Samaguire } 1348*3048Samaguire } 1349*3048Samaguire if (raopt->opt_flags & RA_SVC_FLAG_IPV6_ROUTING) { 1350*3048Samaguire found_proto = B_FALSE; 1351*3048Samaguire if (protolist != NULL) { 1352*3048Samaguire /* Check if protolist contains "ipv6" */ 1353*3048Samaguire for (i = 0; i < numvalues; i++) { 1354*3048Samaguire if (protolist[i] != NULL && strcmp( 1355*3048Samaguire protolist[i], RA_PROPVAL_PROTO_IPV6) == 0) 1356*3048Samaguire found_proto = B_TRUE; 1357*3048Samaguire } 1358*3048Samaguire } 1359*3048Samaguire /* If not an ipv6 routing service, skip. */ 1360*3048Samaguire if (protolist == NULL || !found_proto) { 1361*3048Samaguire ra_free_prop_values(numvalues, protolist); 1362*3048Samaguire return (0); 1363*3048Samaguire } 1364*3048Samaguire } 1365*3048Samaguire ra_free_prop_values(numvalues, protolist); 1366*3048Samaguire 1367*3048Samaguire /* If enabling routing services, select only current routing services */ 1368*3048Samaguire if (raopt->opt_fmri == NULL && !get && raopt->opt_enabled) { 1369*3048Samaguire if (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM, 1370*3048Samaguire RA_PROP_CURR_ROUTING_SVC, B_FALSE, B_FALSE, 1371*3048Samaguire &curr_svc) == -1) 1372*3048Samaguire return (0); 1373*3048Samaguire else if (!curr_svc && persistent) { 1374*3048Samaguire /* 1375*3048Samaguire * We apply "current" routing changes to all routing 1376*3048Samaguire * daemons, whether current or not, so bail if 1377*3048Samaguire * we are trying to make a persistent update to a 1378*3048Samaguire * non-"routing-svc". 1379*3048Samaguire */ 1380*3048Samaguire return (0); 1381*3048Samaguire } 1382*3048Samaguire } 1383*3048Samaguire if (ra_get_boolean_prop(h, inst, SCF_PG_GENERAL, SCF_PROPERTY_ENABLED, 1384*3048Samaguire B_FALSE, B_TRUE, &persistent_state_enabled) == -1) 1385*3048Samaguire return (-1); 1386*3048Samaguire 1387*3048Samaguire current_state_enabled = persistent_state_enabled; 1388*3048Samaguire 1389*3048Samaguire if (ra_get_boolean_prop(h, inst, SCF_PG_GENERAL_OVR, 1390*3048Samaguire SCF_PROPERTY_ENABLED, B_FALSE, B_FALSE, &temporary_state_enabled) 1391*3048Samaguire == 0) 1392*3048Samaguire current_state_enabled = temporary_state_enabled; 1393*3048Samaguire 1394*3048Samaguire if (get) { 1395*3048Samaguire /* 1396*3048Samaguire * Persistent state is enabled if any services are 1397*3048Samaguire * persistently enabled, i.e. general/enabled == true). 1398*3048Samaguire * current state is enabled if any services 1399*3048Samaguire * services are currently enabled, i.e. if defined, 1400*3048Samaguire * general_ovr/enabled == true, if not, general/enabled == true. 1401*3048Samaguire */ 1402*3048Samaguire if (persistent) 1403*3048Samaguire raopt->opt_enabled = raopt->opt_enabled || 1404*3048Samaguire persistent_state_enabled; 1405*3048Samaguire else 1406*3048Samaguire raopt->opt_enabled = raopt->opt_enabled || 1407*3048Samaguire current_state_enabled; 1408*3048Samaguire } else { 1409*3048Samaguire if (persistent) { 1410*3048Samaguire /* 1411*3048Samaguire * For peristent state changes, from -e/-d, 1412*3048Samaguire * we set the general_ovr/enabled value to the 1413*3048Samaguire * current state (to ensure it is preserved), 1414*3048Samaguire * while setting the general/enabled value to 1415*3048Samaguire * the desired value. This has the effect of 1416*3048Samaguire * the desired value coming into effect on next boot. 1417*3048Samaguire */ 1418*3048Samaguire ret = current_state_enabled ? 1419*3048Samaguire smf_enable_instance(inst_fmri, SMF_TEMPORARY) : 1420*3048Samaguire smf_disable_instance(inst_fmri, SMF_TEMPORARY); 1421*3048Samaguire if (ret != 0) { 1422*3048Samaguire (void) fprintf(stderr, gettext( 1423*3048Samaguire "%s: unexpected libscf error: %s\n"), 1424*3048Samaguire myname, scf_strerror(scf_error())); 1425*3048Samaguire return (-1); 1426*3048Samaguire } 1427*3048Samaguire /* 1428*3048Samaguire * Refresh here so general_ovr/enabled state overrides 1429*3048Samaguire * general/enabled state. 1430*3048Samaguire */ 1431*3048Samaguire (void) smf_refresh_instance(inst_fmri); 1432*3048Samaguire /* 1433*3048Samaguire * Now we can safely set the general/enabled value 1434*3048Samaguire * to the value we require on next boot (or 1435*3048Samaguire * "routeadm -u"). 1436*3048Samaguire */ 1437*3048Samaguire ret = ra_set_boolean_prop(h, inst, SCF_PG_GENERAL, 1438*3048Samaguire SCF_PROPERTY_ENABLED, B_FALSE, raopt->opt_enabled); 1439*3048Samaguire if (ret != 0) 1440*3048Samaguire return (-1); 1441*3048Samaguire /* 1442*3048Samaguire * Refresh here so general/enabled value is set. 1443*3048Samaguire */ 1444*3048Samaguire (void) smf_refresh_instance(inst_fmri); 1445*3048Samaguire if (raopt->opt_fmri != NULL) 1446*3048Samaguire return (0); 1447*3048Samaguire /* 1448*3048Samaguire * Notify network/routing-setup service that 1449*3048Samaguire * administrator has explicitly set ipv4(6)-routing 1450*3048Samaguire * value. If no explicit setting of this value is 1451*3048Samaguire * done, ipv4-routing can be enabled in the situation 1452*3048Samaguire * when no default routes can be determined. 1453*3048Samaguire */ 1454*3048Samaguire if ((rinst = scf_instance_create(h)) == NULL || 1455*3048Samaguire scf_handle_decode_fmri(h, RA_INSTANCE_ROUTING_SETUP, 1456*3048Samaguire NULL, NULL, rinst, NULL, NULL, 1457*3048Samaguire SCF_DECODE_FMRI_EXACT) == -1) { 1458*3048Samaguire (void) fprintf(stderr, gettext( 1459*3048Samaguire "%s: unexpected libscf error: %s\n"), 1460*3048Samaguire myname, scf_strerror(scf_error())); 1461*3048Samaguire return (-1); 1462*3048Samaguire } 1463*3048Samaguire ret = ra_set_boolean_prop(h, rinst, RA_PG_ROUTEADM, 1464*3048Samaguire raopt->opt_flags & RA_SVC_FLAG_IPV4_ROUTING ? 1465*3048Samaguire RA_PROP_IPV4_ROUTING_SET : 1466*3048Samaguire RA_PROP_IPV6_ROUTING_SET, B_FALSE, B_TRUE); 1467*3048Samaguire scf_instance_destroy(rinst); 1468*3048Samaguire if (ret != 0) 1469*3048Samaguire return (-1); 1470*3048Samaguire (void) smf_refresh_instance(RA_INSTANCE_ROUTING_SETUP); 1471*3048Samaguire } else { 1472*3048Samaguire /* 1473*3048Samaguire * For current changes (result of -u), we 1474*3048Samaguire * enable/disable depending on persistent value 1475*3048Samaguire * stored in general/enabled. Here we disable 1476*3048Samaguire * old routing-svcs (identified by a current-routing-svc 1477*3048Samaguire * value of false) also. 1478*3048Samaguire */ 1479*3048Samaguire ret = persistent_state_enabled && curr_svc ? 1480*3048Samaguire smf_enable_instance(inst_fmri, 0) : 1481*3048Samaguire smf_disable_instance(inst_fmri, 0); 1482*3048Samaguire if (ret != 0) { 1483*3048Samaguire (void) fprintf(stderr, gettext( 1484*3048Samaguire "%s: unexpected libscf error: %s\n"), 1485*3048Samaguire myname, scf_strerror(scf_error())); 1486*3048Samaguire return (-1); 1487*3048Samaguire } 1488*3048Samaguire (void) smf_refresh_instance(inst_fmri); 1489*3048Samaguire } 1490*3048Samaguire } 1491*3048Samaguire return (0); 1492*3048Samaguire } 1493*3048Samaguire 1494*3048Samaguire static int 1495*3048Samaguire ra_set_default_opt_cb(void *data, scf_walkinfo_t *wip) 1496*3048Samaguire { 1497*3048Samaguire scf_instance_t *inst = wip->inst; 1498*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1499*3048Samaguire raopt_t *raopt = data; 1500*3048Samaguire 1501*3048Samaguire return (ra_set_boolean_prop(h, inst, RA_PG_ROUTEADM, 1502*3048Samaguire raopt->opt_default_prop, B_FALSE, raopt->opt_default_enabled)); 1503*3048Samaguire } 1504*3048Samaguire 1505*3048Samaguire static int 1506*3048Samaguire ra_get_default_opt_cb(void *data, scf_walkinfo_t *wip) 1507*3048Samaguire { 1508*3048Samaguire scf_instance_t *inst = wip->inst; 1509*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1510*3048Samaguire raopt_t *raopt = data; 1511*3048Samaguire 1512*3048Samaguire return (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM, 1513*3048Samaguire raopt->opt_default_prop, B_TRUE, B_TRUE, 1514*3048Samaguire &(raopt->opt_default_enabled))); 1515*3048Samaguire } 1516*3048Samaguire 1517*3048Samaguire /* 1518*3048Samaguire * Callbacks to set/retrieve persistent/default routing variable values. 1519*3048Samaguire * The set functions use the value stored in the var_value/var_default_value 1520*3048Samaguire * field of the associated ra_var_t, while the retrieval functions store 1521*3048Samaguire * the value retrieved in that field. 1522*3048Samaguire */ 1523*3048Samaguire static int 1524*3048Samaguire ra_get_persistent_var_cb(void *data, scf_walkinfo_t *wip) 1525*3048Samaguire { 1526*3048Samaguire scf_instance_t *inst = wip->inst; 1527*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1528*3048Samaguire ravar_t *ravar = data; 1529*3048Samaguire 1530*3048Samaguire return (ra_get_single_prop_as_string(h, inst, RA_PG_ROUTEADM, 1531*3048Samaguire ravar->var_prop, B_TRUE, B_TRUE, NULL, &ravar->var_value)); 1532*3048Samaguire } 1533*3048Samaguire 1534*3048Samaguire static int 1535*3048Samaguire ra_set_persistent_var_cb(void *data, scf_walkinfo_t *wip) 1536*3048Samaguire { 1537*3048Samaguire scf_instance_t *inst = wip->inst; 1538*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1539*3048Samaguire ravar_t *ravar = data; 1540*3048Samaguire 1541*3048Samaguire return (ra_set_prop_from_string(h, inst, RA_PG_ROUTEADM, 1542*3048Samaguire ravar->var_prop, SCF_TYPE_INVALID, B_FALSE, 1, 1543*3048Samaguire (const char **)&ravar->var_value)); 1544*3048Samaguire } 1545*3048Samaguire 1546*3048Samaguire static int 1547*3048Samaguire ra_get_default_var_cb(void *data, scf_walkinfo_t *wip) 1548*3048Samaguire { 1549*3048Samaguire scf_instance_t *inst = wip->inst; 1550*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1551*3048Samaguire ravar_t *ravar = data; 1552*3048Samaguire 1553*3048Samaguire return (ra_get_single_prop_as_string(h, inst, RA_PG_ROUTEADM, 1554*3048Samaguire ravar->var_default_prop, B_TRUE, B_TRUE, NULL, 1555*3048Samaguire &ravar->var_default_value)); 1556*3048Samaguire } 1557*3048Samaguire 1558*3048Samaguire /* 1559*3048Samaguire * Depending on the value of the boolean_t * passed in, this callback 1560*3048Samaguire * either marks the relevant service(s) as current-routing-svcs (or unmarking) 1561*3048Samaguire * by setting that property to true or false. When routing services 1562*3048Samaguire * are to be enabled, the a current-routing-svc value of true flags the 1563*3048Samaguire * service as one to be enabled. 1564*3048Samaguire */ 1565*3048Samaguire static int 1566*3048Samaguire ra_mark_routing_svcs_cb(void *data, scf_walkinfo_t *wip) 1567*3048Samaguire { 1568*3048Samaguire scf_instance_t *inst = wip->inst; 1569*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1570*3048Samaguire boolean_t *mark = data; 1571*3048Samaguire boolean_t marked; 1572*3048Samaguire int numvalues = 0; 1573*3048Samaguire char **protolist = NULL; 1574*3048Samaguire 1575*3048Samaguire /* Check we are dealing with a routing daemon service */ 1576*3048Samaguire if (ra_get_prop_as_string(h, inst, RA_PG_ROUTEADM, RA_PROP_PROTO, 1577*3048Samaguire B_TRUE, B_FALSE, NULL, &numvalues, &protolist) == -1) 1578*3048Samaguire return (0); 1579*3048Samaguire ra_free_prop_values(numvalues, protolist); 1580*3048Samaguire if (*mark) 1581*3048Samaguire return (ra_set_boolean_prop(h, inst, RA_PG_ROUTEADM, 1582*3048Samaguire RA_PROP_CURR_ROUTING_SVC, B_TRUE, B_TRUE)); 1583*3048Samaguire /* Unmark service. */ 1584*3048Samaguire if (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM, 1585*3048Samaguire RA_PROP_CURR_ROUTING_SVC, B_TRUE, B_FALSE, &marked) == 0 && marked) 1586*3048Samaguire return (ra_set_boolean_prop(h, inst, RA_PG_ROUTEADM, 1587*3048Samaguire RA_PROP_CURR_ROUTING_SVC, B_TRUE, B_FALSE)); 1588*3048Samaguire return (0); 1589*3048Samaguire } 1590*3048Samaguire 1591*3048Samaguire /* 1592*3048Samaguire * List property values for all properties in the "routing" property 1593*3048Samaguire * group of the routing service instance. 1594*3048Samaguire */ 1595*3048Samaguire 1596*3048Samaguire /* ARGSUSED0 */ 1597*3048Samaguire static int 1598*3048Samaguire ra_list_props_cb(void *data, scf_walkinfo_t *wip) 1599*3048Samaguire { 1600*3048Samaguire const char *inst_fmri = wip->fmri; 1601*3048Samaguire scf_instance_t *inst = wip->inst; 1602*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1603*3048Samaguire scf_iter_t *propiter, *valiter; 1604*3048Samaguire scf_propertygroup_t *pg; 1605*3048Samaguire scf_property_t *prop; 1606*3048Samaguire scf_value_t *val; 1607*3048Samaguire char **protolist = NULL, *pnamebuf, *valbuf; 1608*3048Samaguire ssize_t pnamelen, vallen; 1609*3048Samaguire int numvalues = 0; 1610*3048Samaguire int propiterret, valiterret, retval = 0; 1611*3048Samaguire 1612*3048Samaguire /* Services with no "protocol" property are not routing daemons */ 1613*3048Samaguire if (ra_get_prop_as_string(h, inst, RA_PG_ROUTEADM, RA_PROP_PROTO, 1614*3048Samaguire B_TRUE, B_FALSE, NULL, &numvalues, &protolist) == -1) { 1615*3048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) 1616*3048Samaguire (void) fprintf(stderr, 1617*3048Samaguire gettext("%s: %s is not a routing daemon service\n"), 1618*3048Samaguire myname, inst_fmri); 1619*3048Samaguire else 1620*3048Samaguire (void) fprintf(stderr, 1621*3048Samaguire gettext("%s: unexpected libscf error: %s\n"), 1622*3048Samaguire myname, scf_strerror(scf_error())); 1623*3048Samaguire ra_free_prop_values(numvalues, protolist); 1624*3048Samaguire return (-1); 1625*3048Samaguire } 1626*3048Samaguire ra_free_prop_values(numvalues, protolist); 1627*3048Samaguire 1628*3048Samaguire if (ra_get_pg(h, inst, RA_PG_ROUTING, B_TRUE, B_FALSE, &pg) == -1) { 1629*3048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) { 1630*3048Samaguire (void) printf("%s: no %s property group for %s\n", 1631*3048Samaguire myname, RA_PG_ROUTING, inst_fmri); 1632*3048Samaguire return (0); 1633*3048Samaguire } 1634*3048Samaguire (void) fprintf(stderr, 1635*3048Samaguire gettext("%s: unexpected libscf error: %s\n"), 1636*3048Samaguire myname, scf_strerror(scf_error())); 1637*3048Samaguire return (-1); 1638*3048Samaguire } 1639*3048Samaguire 1640*3048Samaguire (void) printf("%s:\n", inst_fmri); 1641*3048Samaguire 1642*3048Samaguire /* Create an iterator to walk through all properties */ 1643*3048Samaguire if ((propiter = scf_iter_create(h)) == NULL || 1644*3048Samaguire (prop = scf_property_create(h)) == NULL || 1645*3048Samaguire scf_iter_pg_properties(propiter, pg) != 0) { 1646*3048Samaguire (void) fprintf(stderr, gettext 1647*3048Samaguire ("%s: could not iterate through properties for %s: %s\n"), 1648*3048Samaguire myname, inst_fmri, scf_strerror(scf_error())); 1649*3048Samaguire } 1650*3048Samaguire while ((propiterret = scf_iter_next_property(propiter, prop)) == 1) { 1651*3048Samaguire if ((pnamelen = scf_property_get_name(prop, NULL, 0) + 1) 1652*3048Samaguire == 0) { 1653*3048Samaguire (void) fprintf(stderr, gettext("%s: could not retrieve " 1654*3048Samaguire "property name for instance %s: %s\n"), myname, 1655*3048Samaguire inst_fmri, scf_strerror(scf_error())); 1656*3048Samaguire retval = -1; 1657*3048Samaguire break; 1658*3048Samaguire } 1659*3048Samaguire if ((pnamebuf = malloc(pnamelen)) == NULL) { 1660*3048Samaguire (void) fprintf(stderr, 1661*3048Samaguire gettext("%s: out of memory\n"), myname); 1662*3048Samaguire retval = -1; 1663*3048Samaguire break; 1664*3048Samaguire } 1665*3048Samaguire (void) scf_property_get_name(prop, pnamebuf, 1666*3048Samaguire pnamelen); 1667*3048Samaguire (void) printf("\t%s = ", pnamebuf); 1668*3048Samaguire if ((valiter = scf_iter_create(h)) == NULL || 1669*3048Samaguire (val = scf_value_create(h)) == NULL || 1670*3048Samaguire scf_iter_property_values(valiter, prop) 1671*3048Samaguire != 0) { 1672*3048Samaguire (void) fprintf(stderr, gettext 1673*3048Samaguire ("%s: could not iterate through " 1674*3048Samaguire "properties for %s: %s\n"), myname, inst_fmri, 1675*3048Samaguire scf_strerror(scf_error())); 1676*3048Samaguire scf_value_destroy(val); 1677*3048Samaguire scf_iter_destroy(valiter); 1678*3048Samaguire free(pnamebuf); 1679*3048Samaguire retval = -1; 1680*3048Samaguire break; 1681*3048Samaguire } 1682*3048Samaguire while ((valiterret = scf_iter_next_value(valiter, val)) == 1) { 1683*3048Samaguire if ((vallen = scf_value_get_as_string 1684*3048Samaguire (val, NULL, 0) + 1) == 0) { 1685*3048Samaguire (void) fprintf(stderr, gettext 1686*3048Samaguire ("%s: could not retrieve " 1687*3048Samaguire "property value for instance %s, " 1688*3048Samaguire "property %s: %s\n"), myname, inst_fmri, 1689*3048Samaguire pnamebuf, scf_strerror(scf_error())); 1690*3048Samaguire retval = -1; 1691*3048Samaguire } else if ((valbuf = malloc(vallen)) == NULL) { 1692*3048Samaguire (void) fprintf(stderr, 1693*3048Samaguire gettext("%s: out of memory\n"), myname); 1694*3048Samaguire retval = -1; 1695*3048Samaguire } 1696*3048Samaguire if (retval == -1) { 1697*3048Samaguire scf_iter_destroy(valiter); 1698*3048Samaguire scf_value_destroy(val); 1699*3048Samaguire free(pnamebuf); 1700*3048Samaguire goto out; 1701*3048Samaguire } 1702*3048Samaguire (void) scf_value_get_as_string(val, valbuf, vallen); 1703*3048Samaguire (void) printf("%s ", valbuf); 1704*3048Samaguire free(valbuf); 1705*3048Samaguire } 1706*3048Samaguire (void) printf("\n"); 1707*3048Samaguire scf_iter_destroy(valiter); 1708*3048Samaguire scf_value_destroy(val); 1709*3048Samaguire free(pnamebuf); 1710*3048Samaguire if (valiterret == -1) { 1711*3048Samaguire (void) fprintf(stderr, 1712*3048Samaguire gettext("%s: could not iterate through" 1713*3048Samaguire "properties for %s: %s\n"), myname, inst_fmri, 1714*3048Samaguire scf_strerror(scf_error())); 1715*3048Samaguire retval = -1; 1716*3048Samaguire break; 1717*3048Samaguire } 1718*3048Samaguire } 1719*3048Samaguire out: 1720*3048Samaguire scf_iter_destroy(propiter); 1721*3048Samaguire scf_property_destroy(prop); 1722*3048Samaguire scf_pg_destroy(pg); 1723*3048Samaguire if (propiterret == -1) 1724*3048Samaguire (void) fprintf(stderr, gettext 1725*3048Samaguire ("%s: could not iterate through properties for %s: %s\n"), 1726*3048Samaguire myname, inst_fmri, scf_strerror(scf_error())); 1727*3048Samaguire return (retval); 1728*3048Samaguire } 1729*3048Samaguire 1730*3048Samaguire /* 1731*3048Samaguire * Modify property with name stored in passed-in ra_prop_t to have 1732*3048Samaguire * the assocatied values. Only works for existing properties in 1733*3048Samaguire * the "routing" property group for routing daemon services, so all 1734*3048Samaguire * routing daemons should place configurable options in that group. 1735*3048Samaguire */ 1736*3048Samaguire static int 1737*3048Samaguire ra_modify_props_cb(void *data, scf_walkinfo_t *wip) 1738*3048Samaguire { 1739*3048Samaguire const char *inst_fmri = wip->fmri; 1740*3048Samaguire scf_instance_t *inst = wip->inst; 1741*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1742*3048Samaguire ra_prop_t *raprop = data; 1743*3048Samaguire int numvalues = 0; 1744*3048Samaguire char **protolist = NULL; 1745*3048Samaguire 1746*3048Samaguire /* Services with no "protocol" property are not routing daemons */ 1747*3048Samaguire if (ra_get_prop_as_string(h, inst, RA_PG_ROUTEADM, RA_PROP_PROTO, 1748*3048Samaguire B_TRUE, B_FALSE, NULL, &numvalues, &protolist) == -1) { 1749*3048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) 1750*3048Samaguire (void) fprintf(stderr, 1751*3048Samaguire gettext("%s: %s is not a routing daemon service\n"), 1752*3048Samaguire myname, inst_fmri); 1753*3048Samaguire else 1754*3048Samaguire (void) fprintf(stderr, 1755*3048Samaguire gettext("%s: unexpected libscf error: %s\n"), 1756*3048Samaguire myname, scf_strerror(scf_error())); 1757*3048Samaguire ra_free_prop_values(numvalues, protolist); 1758*3048Samaguire return (-1); 1759*3048Samaguire } 1760*3048Samaguire ra_free_prop_values(numvalues, protolist); 1761*3048Samaguire 1762*3048Samaguire if (ra_set_prop_from_string(h, inst, RA_PG_ROUTING, raprop->prop_name, 1763*3048Samaguire SCF_TYPE_INVALID, B_FALSE, raprop->prop_numvalues, 1764*3048Samaguire (const char **)raprop->prop_values) == -1) 1765*3048Samaguire return (-1); 1766*3048Samaguire 1767*3048Samaguire (void) smf_refresh_instance(inst_fmri); 1768*3048Samaguire return (0); 1769*3048Samaguire } 1770*3048Samaguire 1771*3048Samaguire /* 1772*3048Samaguire * Display FMRI, state for each routing daemon service. 1773*3048Samaguire */ 1774*3048Samaguire 1775*3048Samaguire /* ARGSUSED0 */ 1776*3048Samaguire static int 1777*3048Samaguire ra_print_state_cb(void *data, scf_walkinfo_t *wip) 1778*3048Samaguire { 1779*3048Samaguire const char *inst_fmri = wip->fmri; 1780*3048Samaguire scf_instance_t *inst = wip->inst; 1781*3048Samaguire scf_handle_t *h = scf_instance_handle(inst); 1782*3048Samaguire char *inst_state, **protolist = NULL; 1783*3048Samaguire int numvalues = 0; 1784*3048Samaguire 1785*3048Samaguire /* Ensure service is a routing daemon */ 1786*3048Samaguire if (ra_get_prop_as_string(h, inst, RA_PG_ROUTEADM, RA_PROP_PROTO, 1787*3048Samaguire B_TRUE, B_FALSE, NULL, &numvalues, &protolist) == -1) 1788*3048Samaguire return (0); 1789*3048Samaguire ra_free_prop_values(numvalues, protolist); 1790*3048Samaguire 1791*3048Samaguire if ((inst_state = smf_get_state(inst_fmri)) == NULL) { 1792*3048Samaguire (void) fprintf(stderr, 1793*3048Samaguire gettext("%s: could not retrieve state for %s: %s\n"), 1794*3048Samaguire myname, inst_fmri, scf_strerror(scf_error())); 1795*3048Samaguire return (-1); 1796*3048Samaguire } 1797*3048Samaguire (void) printf("%27s %2s\n", inst_state, inst_fmri); 1798*3048Samaguire free(inst_state); 1799*3048Samaguire 1800*3048Samaguire return (0); 1801*3048Samaguire } 1802*3048Samaguire 1803*3048Samaguire static int 1804*3048Samaguire ra_get_pg(scf_handle_t *h, scf_instance_t *inst, const char *pgname, 1805*3048Samaguire boolean_t composed, boolean_t required, scf_propertygroup_t **pg) 1806*3048Samaguire { 1807*3048Samaguire /* Retrieve (possibly composed) property group for instance */ 1808*3048Samaguire if ((*pg = scf_pg_create(h)) == NULL || (composed && 1809*3048Samaguire scf_instance_get_pg_composed(inst, NULL, pgname, *pg) != 0) || 1810*3048Samaguire (!composed && scf_instance_get_pg(inst, pgname, *pg) != 0)) { 1811*3048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) { 1812*3048Samaguire if (required) 1813*3048Samaguire (void) fprintf(stderr, gettext( 1814*3048Samaguire "%s: no such property group %s\n"), 1815*3048Samaguire myname, pgname); 1816*3048Samaguire return (-1); 1817*3048Samaguire } 1818*3048Samaguire if (required) 1819*3048Samaguire (void) fprintf(stderr, gettext( 1820*3048Samaguire "%s: unexpected libscf error: %s\n"), myname, 1821*3048Samaguire scf_strerror(scf_error())); 1822*3048Samaguire return (-1); 1823*3048Samaguire } 1824*3048Samaguire return (0); 1825*3048Samaguire } 1826*3048Samaguire 1827*3048Samaguire static int 1828*3048Samaguire ra_get_boolean_prop(scf_handle_t *h, scf_instance_t *inst, 1829*3048Samaguire const char *pgname, const char *propname, boolean_t composed, 1830*3048Samaguire boolean_t required, boolean_t *val) 1831*3048Samaguire { 1832*3048Samaguire char *valstr; 1833*3048Samaguire 1834*3048Samaguire if (ra_get_single_prop_as_string(h, inst, pgname, propname, 1835*3048Samaguire composed, required, NULL, &valstr) != 0) 1836*3048Samaguire return (-1); 1837*3048Samaguire *val = strcmp(valstr, RA_PROPVAL_BOOLEAN_TRUE) == 0; 1838*3048Samaguire free(valstr); 1839*3048Samaguire return (0); 1840*3048Samaguire } 1841*3048Samaguire 1842*3048Samaguire static int 1843*3048Samaguire ra_get_single_prop_as_string(scf_handle_t *h, scf_instance_t *inst, 1844*3048Samaguire const char *pgname, const char *propname, boolean_t composed, 1845*3048Samaguire boolean_t required, scf_type_t *type, char **value) 1846*3048Samaguire { 1847*3048Samaguire char **values; 1848*3048Samaguire int numvalues = 1; 1849*3048Samaguire 1850*3048Samaguire if (ra_get_prop_as_string(h, inst, pgname, propname, composed, required, 1851*3048Samaguire type, &numvalues, &values) == -1) 1852*3048Samaguire return (-1); 1853*3048Samaguire *value = values[0]; 1854*3048Samaguire free(values); 1855*3048Samaguire return (0); 1856*3048Samaguire } 1857*3048Samaguire 1858*3048Samaguire /* 1859*3048Samaguire * Retrieve property named in propname, possibly using the composed 1860*3048Samaguire * property group view (union of instance and service-level properties, 1861*3048Samaguire * where instance-level properties override service-level values). 1862*3048Samaguire */ 1863*3048Samaguire static int 1864*3048Samaguire ra_get_prop_as_string(scf_handle_t *h, scf_instance_t *inst, 1865*3048Samaguire const char *pgname, const char *propname, boolean_t composed, 1866*3048Samaguire boolean_t required, scf_type_t *type, int *numvalues, char ***values) 1867*3048Samaguire { 1868*3048Samaguire scf_propertygroup_t *pg = NULL; 1869*3048Samaguire scf_property_t *prop = NULL; 1870*3048Samaguire scf_iter_t *valiter = NULL; 1871*3048Samaguire scf_value_t *val = NULL; 1872*3048Samaguire ssize_t vallen = 0; 1873*3048Samaguire int valiterret, i, numvalues_retrieved, ret = 0; 1874*3048Samaguire 1875*3048Samaguire if (ra_get_pg(h, inst, pgname, composed, required, &pg) == -1) 1876*3048Samaguire return (-1); 1877*3048Samaguire 1878*3048Samaguire *values = NULL; 1879*3048Samaguire /* 1880*3048Samaguire * Retrieve values. All values routeadm needs to retrieve 1881*3048Samaguire * (bar those gathered by routeadm -l), are known to be single-valued. 1882*3048Samaguire */ 1883*3048Samaguire if ((prop = scf_property_create(h)) == NULL) 1884*3048Samaguire goto error; 1885*3048Samaguire if (scf_pg_get_property(pg, propname, prop) != 0) { 1886*3048Samaguire *numvalues = 0; 1887*3048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) { 1888*3048Samaguire if (required) 1889*3048Samaguire (void) fprintf(stderr, gettext( 1890*3048Samaguire "%s: property %s/%s not found\n"), 1891*3048Samaguire myname, pgname, propname); 1892*3048Samaguire ret = -1; 1893*3048Samaguire goto out; 1894*3048Samaguire } 1895*3048Samaguire goto error; 1896*3048Samaguire } 1897*3048Samaguire if ((val = scf_value_create(h)) == NULL && 1898*3048Samaguire scf_property_get_value(prop, val) != 0 || 1899*3048Samaguire (valiter = scf_iter_create(h)) == NULL || 1900*3048Samaguire scf_iter_property_values(valiter, prop) != 0) 1901*3048Samaguire goto error; 1902*3048Samaguire /* retrieve each value */ 1903*3048Samaguire for (numvalues_retrieved = 0; 1904*3048Samaguire (valiterret = scf_iter_next_value(valiter, val)) == 1; 1905*3048Samaguire numvalues_retrieved++) { 1906*3048Samaguire if ((vallen = scf_value_get_as_string 1907*3048Samaguire (val, NULL, 0) + 1) == 0) 1908*3048Samaguire goto error; 1909*3048Samaguire if ((*values = realloc(*values, 1910*3048Samaguire sizeof (*values) + sizeof (char *))) == NULL || 1911*3048Samaguire ((*values)[numvalues_retrieved] = malloc(vallen)) == NULL) { 1912*3048Samaguire (void) fprintf(stderr, gettext( 1913*3048Samaguire "%s: out of memory\n"), myname); 1914*3048Samaguire ret = -1; 1915*3048Samaguire goto out; 1916*3048Samaguire } 1917*3048Samaguire (void) scf_value_get_as_string(val, 1918*3048Samaguire (*values)[numvalues_retrieved], vallen); 1919*3048Samaguire } 1920*3048Samaguire if (valiterret == -1) 1921*3048Samaguire goto error; 1922*3048Samaguire /* 1923*3048Samaguire * if *numvalues != 0, it holds expected number of values. If a 1924*3048Samaguire * different number are found, it is an error. 1925*3048Samaguire */ 1926*3048Samaguire if (*numvalues != 0 && *numvalues != numvalues_retrieved) { 1927*3048Samaguire (void) fprintf(stderr, gettext( 1928*3048Samaguire "%s: got %d values for property %s/%s, expected %d\n"), 1929*3048Samaguire myname, numvalues_retrieved, pgname, propname, *numvalues); 1930*3048Samaguire ret = -1; 1931*3048Samaguire goto out; 1932*3048Samaguire } 1933*3048Samaguire *numvalues = numvalues_retrieved; 1934*3048Samaguire 1935*3048Samaguire /* Retrieve property type if required. */ 1936*3048Samaguire if (type != NULL) 1937*3048Samaguire (void) scf_property_type(prop, type); 1938*3048Samaguire 1939*3048Samaguire goto out; 1940*3048Samaguire error: 1941*3048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) { 1942*3048Samaguire (void) fprintf(stderr, gettext( 1943*3048Samaguire "%s: property %s not found"), myname, propname); 1944*3048Samaguire } else { 1945*3048Samaguire (void) fprintf(stderr, gettext( 1946*3048Samaguire "%s: unexpected libscf error: %s, "), myname); 1947*3048Samaguire } 1948*3048Samaguire for (i = 0; i < numvalues_retrieved; i++) 1949*3048Samaguire free((*values)[i]); 1950*3048Samaguire if (*values != NULL) 1951*3048Samaguire free(*values); 1952*3048Samaguire 1953*3048Samaguire ret = -1; 1954*3048Samaguire out: 1955*3048Samaguire if (val != NULL) 1956*3048Samaguire scf_value_destroy(val); 1957*3048Samaguire if (valiter != NULL) 1958*3048Samaguire scf_iter_destroy(valiter); 1959*3048Samaguire if (prop != NULL) 1960*3048Samaguire scf_property_destroy(prop); 1961*3048Samaguire if (pg != NULL) 1962*3048Samaguire scf_pg_destroy(pg); 1963*3048Samaguire return (ret); 1964*3048Samaguire } 1965*3048Samaguire 1966*3048Samaguire static void 1967*3048Samaguire ra_free_prop_values(int numvalues, char **values) 1968*3048Samaguire { 1969*3048Samaguire int i; 1970*3048Samaguire if (values != NULL) { 1971*3048Samaguire for (i = 0; i < numvalues; i++) 1972*3048Samaguire free(values[i]); 1973*3048Samaguire free(values); 1974*3048Samaguire } 1975*3048Samaguire } 1976*3048Samaguire 1977*3048Samaguire static int 1978*3048Samaguire ra_set_boolean_prop(scf_handle_t *h, scf_instance_t *inst, const char *pgname, 1979*3048Samaguire const char *prop, boolean_t create, boolean_t propval) 1980*3048Samaguire { 1981*3048Samaguire const char *val = propval ? RA_PROPVAL_BOOLEAN_TRUE : 1982*3048Samaguire RA_PROPVAL_BOOLEAN_FALSE; 1983*3048Samaguire 1984*3048Samaguire return (ra_set_prop_from_string(h, inst, pgname, prop, SCF_TYPE_BOOLEAN, 1985*3048Samaguire create, 1, &val)); 1986*3048Samaguire } 1987*3048Samaguire 1988*3048Samaguire /* 1989*3048Samaguire * Set the property named in propname to the values passed in in the propvals 1990*3048Samaguire * array. Only create a new property if "create" is true. 1991*3048Samaguire */ 1992*3048Samaguire static int 1993*3048Samaguire ra_set_prop_from_string(scf_handle_t *h, scf_instance_t *inst, 1994*3048Samaguire const char *pgname, const char *propname, scf_type_t proptype, 1995*3048Samaguire boolean_t create, int numpropvals, const char **propvals) 1996*3048Samaguire { 1997*3048Samaguire scf_propertygroup_t *instpg = NULL, *cpg = NULL; 1998*3048Samaguire scf_type_t oldproptype, newproptype = proptype; 1999*3048Samaguire scf_property_t *prop = NULL; 2000*3048Samaguire scf_value_t **values = NULL; 2001*3048Samaguire scf_transaction_t *tx = NULL; 2002*3048Samaguire scf_transaction_entry_t *ent = NULL; 2003*3048Samaguire boolean_t new = B_FALSE; 2004*3048Samaguire int i, retval, numvalues = 0, ret = 0; 2005*3048Samaguire char *pgtype = NULL, **ovalues; 2006*3048Samaguire ssize_t typelen; 2007*3048Samaguire 2008*3048Samaguire /* Firstly, does property exist? If not, and create is false, bail */ 2009*3048Samaguire if (ra_get_prop_as_string(h, inst, pgname, propname, B_TRUE, 2010*3048Samaguire B_FALSE, &oldproptype, &numvalues, &ovalues) == -1) { 2011*3048Samaguire if (scf_error() != SCF_ERROR_NOT_FOUND) 2012*3048Samaguire goto error; 2013*3048Samaguire if (!create) { 2014*3048Samaguire (void) fprintf(stderr, gettext( 2015*3048Samaguire "%s: no such property %s/%s\n"), myname, pgname, 2016*3048Samaguire propname); 2017*3048Samaguire return (-1); 2018*3048Samaguire } 2019*3048Samaguire } else 2020*3048Samaguire ra_free_prop_values(numvalues, ovalues); 2021*3048Samaguire 2022*3048Samaguire /* Use old property type */ 2023*3048Samaguire if (proptype == SCF_TYPE_INVALID) 2024*3048Samaguire newproptype = oldproptype; 2025*3048Samaguire 2026*3048Samaguire /* 2027*3048Samaguire * Does property group exist at instance level? If not, we need to 2028*3048Samaguire * create it, since the composed view of the property group did 2029*3048Samaguire * contain the property. We never modify properties at the service 2030*3048Samaguire * level, as it`s possible that multiple instances will inherit those 2031*3048Samaguire * settings. 2032*3048Samaguire */ 2033*3048Samaguire if (ra_get_pg(h, inst, pgname, B_FALSE, B_FALSE, &instpg) == -1) { 2034*3048Samaguire if (scf_error() != SCF_ERROR_NOT_FOUND) 2035*3048Samaguire goto error; 2036*3048Samaguire /* Ensure pg exists at service level, get composed pg */ 2037*3048Samaguire if (ra_get_pg(h, inst, pgname, B_TRUE, B_FALSE, &cpg) == -1) 2038*3048Samaguire goto error; 2039*3048Samaguire 2040*3048Samaguire /* Create instance-level property group */ 2041*3048Samaguire if ((typelen = scf_pg_get_type(cpg, NULL, 0) + 1) == 0) 2042*3048Samaguire goto error; 2043*3048Samaguire if ((pgtype = malloc(typelen)) == NULL) { 2044*3048Samaguire (void) fprintf(stderr, gettext( 2045*3048Samaguire "%s: out of memory\n"), myname); 2046*3048Samaguire goto error; 2047*3048Samaguire } 2048*3048Samaguire (void) scf_pg_get_type(cpg, pgtype, typelen); 2049*3048Samaguire if ((instpg = scf_pg_create(h)) == NULL || 2050*3048Samaguire scf_instance_add_pg(inst, pgname, pgtype, 0, instpg) 2051*3048Samaguire == -1) { 2052*3048Samaguire (void) fprintf(stderr, gettext( 2053*3048Samaguire "%s: could not create property group %s\n"), 2054*3048Samaguire myname, pgname); 2055*3048Samaguire goto error; 2056*3048Samaguire } 2057*3048Samaguire } 2058*3048Samaguire if ((prop = scf_property_create(h)) == NULL) 2059*3048Samaguire goto error; 2060*3048Samaguire if ((values = calloc(numpropvals, sizeof (scf_value_t *))) == NULL) { 2061*3048Samaguire (void) fprintf(stderr, gettext("%s: out of memory"), myname); 2062*3048Samaguire goto error; 2063*3048Samaguire } 2064*3048Samaguire if (scf_pg_get_property(instpg, propname, prop) != 0) { 2065*3048Samaguire /* New property? */ 2066*3048Samaguire if (scf_error() == SCF_ERROR_NOT_FOUND) 2067*3048Samaguire new = B_TRUE; 2068*3048Samaguire else 2069*3048Samaguire goto error; 2070*3048Samaguire } 2071*3048Samaguire if ((tx = scf_transaction_create(h)) == NULL || 2072*3048Samaguire (ent = scf_entry_create(h)) == NULL) 2073*3048Samaguire goto error; 2074*3048Samaguire retry: 2075*3048Samaguire if (scf_transaction_start(tx, instpg) == -1) 2076*3048Samaguire goto error; 2077*3048Samaguire if (new) { 2078*3048Samaguire if (scf_transaction_property_new(tx, ent, propname, 2079*3048Samaguire newproptype) == -1) 2080*3048Samaguire goto error; 2081*3048Samaguire } else if (scf_transaction_property_change(tx, ent, propname, 2082*3048Samaguire newproptype) == -1) 2083*3048Samaguire goto error; 2084*3048Samaguire for (i = 0; i < numpropvals; i++) { 2085*3048Samaguire if ((values[i] = scf_value_create(h)) == NULL || 2086*3048Samaguire scf_value_set_from_string(values[i], newproptype, 2087*3048Samaguire propvals[i] == NULL ? "": propvals[i]) == -1 || 2088*3048Samaguire scf_entry_add_value(ent, values[i]) != 0) 2089*3048Samaguire goto error; 2090*3048Samaguire } 2091*3048Samaguire retval = scf_transaction_commit(tx); 2092*3048Samaguire if (retval == 0) { 2093*3048Samaguire scf_transaction_reset(tx); 2094*3048Samaguire if (scf_pg_update(instpg) == -1) 2095*3048Samaguire goto error; 2096*3048Samaguire goto retry; 2097*3048Samaguire } 2098*3048Samaguire if (retval == -1) 2099*3048Samaguire goto error; 2100*3048Samaguire goto out; 2101*3048Samaguire error: 2102*3048Samaguire switch (scf_error()) { 2103*3048Samaguire case SCF_ERROR_INVALID_ARGUMENT: 2104*3048Samaguire (void) fprintf(stderr, gettext( 2105*3048Samaguire "%s: invalid value for property %s/%s\n"), myname, 2106*3048Samaguire pgname, propname); 2107*3048Samaguire break; 2108*3048Samaguire case SCF_ERROR_NOT_FOUND: 2109*3048Samaguire (void) fprintf(stderr, gettext( 2110*3048Samaguire "%s: no such property %s/%s\n"), myname, 2111*3048Samaguire pgname, propname); 2112*3048Samaguire break; 2113*3048Samaguire default: 2114*3048Samaguire (void) fprintf(stderr, gettext( 2115*3048Samaguire "%s: unexpected libscf error: %s\n"), myname, 2116*3048Samaguire scf_strerror(scf_error())); 2117*3048Samaguire break; 2118*3048Samaguire } 2119*3048Samaguire ret = -1; 2120*3048Samaguire out: 2121*3048Samaguire if (tx != NULL) 2122*3048Samaguire scf_transaction_destroy(tx); 2123*3048Samaguire if (ent != NULL) 2124*3048Samaguire scf_entry_destroy(ent); 2125*3048Samaguire if (values != NULL) { 2126*3048Samaguire for (i = 0; i < numpropvals; i++) { 2127*3048Samaguire if (values[i] != NULL) 2128*3048Samaguire scf_value_destroy(values[i]); 2129*3048Samaguire } 2130*3048Samaguire free(values); 2131*3048Samaguire } 2132*3048Samaguire if (prop != NULL) 2133*3048Samaguire scf_property_destroy(prop); 2134*3048Samaguire if (cpg != NULL) 2135*3048Samaguire scf_pg_destroy(cpg); 2136*3048Samaguire if (instpg != NULL) 2137*3048Samaguire scf_pg_destroy(instpg); 2138*3048Samaguire if (pgtype != NULL) 2139*3048Samaguire free(pgtype); 2140*3048Samaguire return (ret); 2141*3048Samaguire } 2142*3048Samaguire 2143*3048Samaguire /* 2144*3048Samaguire * This function gathers configuration from the legacy /etc/inet/routing.conf, 2145*3048Samaguire * if any, and sets the appropriate variable values accordingly. Once 2146*3048Samaguire * these are set, the legacy daemons are checked to see if they have 2147*3048Samaguire * SMF counterparts (ra_check_legacy_daemons()). If they do, the 2148*3048Samaguire * configuration is upgraded. Finally, the legacy option settings are 2149*3048Samaguire * applied, enabling/disabling the routing/forwarding services as 2150*3048Samaguire * appropriate. 2151*3048Samaguire */ 2152*3048Samaguire static int 2153*3048Samaguire ra_upgrade_from_legacy_conf(void) 2154*3048Samaguire { 2155*3048Samaguire scf_handle_t *h = NULL; 2156*3048Samaguire scf_instance_t *inst = NULL; 2157*3048Samaguire int ret = 0, i, r; 2158*3048Samaguire boolean_t old_conf_read; 2159*3048Samaguire ravar_t *routing_svcs = ra_str2var(RA_VAR_ROUTING_SVCS); 2160*3048Samaguire 2161*3048Samaguire /* 2162*3048Samaguire * First, determine if we have already upgraded - if "routing-conf-read" 2163*3048Samaguire * is true, we bail. The use of a boolean property indicating if 2164*3048Samaguire * routing.conf has been read and applied might seem a lot more 2165*3048Samaguire * work than simply copying routing.conf aside, but leaving the 2166*3048Samaguire * file in place allows users to downgrade and have their old 2167*3048Samaguire * routing configuration still in place. 2168*3048Samaguire */ 2169*3048Samaguire if ((h = scf_handle_create(SCF_VERSION)) == NULL || 2170*3048Samaguire scf_handle_bind(h) == -1) { 2171*3048Samaguire (void) fprintf(stderr, gettext( 2172*3048Samaguire "%s: cannot connect to SMF repository\n"), myname); 2173*3048Samaguire ret = -1; 2174*3048Samaguire goto out; 2175*3048Samaguire } 2176*3048Samaguire if ((inst = scf_instance_create(h)) == NULL || 2177*3048Samaguire scf_handle_decode_fmri(h, RA_INSTANCE_ROUTING_SETUP, 2178*3048Samaguire NULL, NULL, inst, NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) { 2179*3048Samaguire (void) fprintf(stderr, gettext( 2180*3048Samaguire "%s: unexpected libscf error: %s\n"), myname, 2181*3048Samaguire scf_strerror(scf_error())); 2182*3048Samaguire ret = -1; 2183*3048Samaguire goto out; 2184*3048Samaguire } 2185*3048Samaguire if (ra_get_boolean_prop(h, inst, RA_PG_ROUTEADM, 2186*3048Samaguire RA_PROP_ROUTING_CONF_READ, B_TRUE, B_TRUE, &old_conf_read) == -1) { 2187*3048Samaguire ret = -1; 2188*3048Samaguire goto out; 2189*3048Samaguire } 2190*3048Samaguire 2191*3048Samaguire if (old_conf_read) 2192*3048Samaguire goto out; 2193*3048Samaguire 2194*3048Samaguire /* 2195*3048Samaguire * Now set "routing-conf-read" to true so we don`t reimport legacy 2196*3048Samaguire * configuration again. 2197*3048Samaguire */ 2198*3048Samaguire if (ra_set_boolean_prop(h, inst, RA_PG_ROUTEADM, 2199*3048Samaguire RA_PROP_ROUTING_CONF_READ, B_FALSE, B_TRUE) == -1) 2200*3048Samaguire return (-1); 2201*3048Samaguire (void) smf_refresh_instance(RA_INSTANCE_ROUTING_SETUP); 2202*3048Samaguire 2203*3048Samaguire ra_resetvars(NULL); 2204*3048Samaguire 2205*3048Samaguire /* First, gather values from routing.conf */ 2206*3048Samaguire if ((r = ra_parseconf()) == -1) { 2207*3048Samaguire ret = -1; 2208*3048Samaguire goto out; 2209*3048Samaguire } 2210*3048Samaguire /* No routing.conf file found */ 2211*3048Samaguire if (r == 0) 2212*3048Samaguire goto out; 2213*3048Samaguire /* 2214*3048Samaguire * Now, set the options/variables gathered. We set variables first, 2215*3048Samaguire * as we cannot enable routing before we determine the daemons 2216*3048Samaguire * to enable. 2217*3048Samaguire */ 2218*3048Samaguire 2219*3048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) { 2220*3048Samaguire /* Skip routing-svcs var, not featured in legacy config */ 2221*3048Samaguire if (strcmp(ra_vars[i].var_name, RA_VAR_ROUTING_SVCS) == 0) 2222*3048Samaguire continue; 2223*3048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb, ra_vars[i].var_fmri, 2224*3048Samaguire &(ra_vars[i])) == -1) { 2225*3048Samaguire ret = -1; 2226*3048Samaguire goto out; 2227*3048Samaguire } 2228*3048Samaguire } 2229*3048Samaguire /* Clear routing-svcs value */ 2230*3048Samaguire if (ra_smf_cb(ra_set_persistent_var_cb, routing_svcs->var_fmri, 2231*3048Samaguire routing_svcs) == -1) { 2232*3048Samaguire ret = -1; 2233*3048Samaguire goto out; 2234*3048Samaguire } 2235*3048Samaguire 2236*3048Samaguire if (ra_check_legacy_daemons() == -1) { 2237*3048Samaguire ret = -1; 2238*3048Samaguire goto out; 2239*3048Samaguire } 2240*3048Samaguire 2241*3048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) { 2242*3048Samaguire if (ra_smf_cb(ra_set_persistent_opt_cb, ra_opts[i].opt_fmri, 2243*3048Samaguire &(ra_opts[i])) == -1 || 2244*3048Samaguire ra_smf_cb(ra_set_default_opt_cb, 2245*3048Samaguire ra_opts[i].opt_default_fmri, &(ra_opts[i])) == -1) { 2246*3048Samaguire ret = -1; 2247*3048Samaguire break; 2248*3048Samaguire } 2249*3048Samaguire } 2250*3048Samaguire out: 2251*3048Samaguire if (inst != NULL) 2252*3048Samaguire scf_instance_destroy(inst); 2253*3048Samaguire if (h != NULL) 2254*3048Samaguire scf_handle_destroy(h); 2255*3048Samaguire 2256*3048Samaguire return (ret); 2257*3048Samaguire } 2258*3048Samaguire 2259*3048Samaguire /* 2260*3048Samaguire * Parse the configuration file and fill the ra_opts array with opt_value 2261*3048Samaguire * and opt_default_value values, and the ra_vars array with var_value and 2262*3048Samaguire * var_default_value values. Then copy aside routing.conf so it will not 2263*3048Samaguire * be read by future invokations of routeadm. 2264*3048Samaguire */ 2265*3048Samaguire static int 2266*3048Samaguire ra_parseconf(void) 2267*3048Samaguire { 2268*3048Samaguire FILE *fp; 2269*3048Samaguire uint_t lineno; 2270*3048Samaguire char line[RA_MAX_CONF_LINE]; 2271*3048Samaguire char *cp, *confstr; 2272*3048Samaguire raopt_t *raopt; 2273*3048Samaguire ravar_t *ravar; 2274*3048Samaguire 2275*3048Samaguire if ((fp = fopen(RA_CONF_FILE, "r")) == NULL) { 2276*3048Samaguire /* 2277*3048Samaguire * There's no config file, so we simply return as there 2278*3048Samaguire * is no work to do. 2279*3048Samaguire */ 2280*3048Samaguire return (0); 2281*3048Samaguire } 2282*3048Samaguire 2283*3048Samaguire for (lineno = 1; fgets(line, sizeof (line), fp) != NULL; lineno++) { 2284*3048Samaguire if (line[strlen(line) - 1] == '\n') 2285*3048Samaguire line[strlen(line) - 1] = '\0'; 2286*3048Samaguire 2287*3048Samaguire cp = line; 2288*3048Samaguire 2289*3048Samaguire /* Skip leading whitespace */ 2290*3048Samaguire while (isspace(*cp)) 2291*3048Samaguire cp++; 2292*3048Samaguire 2293*3048Samaguire /* Skip comment lines and empty lines */ 2294*3048Samaguire if (*cp == '#' || *cp == '\0') 2295*3048Samaguire continue; 2296*3048Samaguire 2297*3048Samaguire /* 2298*3048Samaguire * Anything else must be of the form: 2299*3048Samaguire * <option> <value> <default_value> 2300*3048Samaguire */ 2301*3048Samaguire if ((confstr = strtok(cp, " ")) == NULL) { 2302*3048Samaguire (void) fprintf(stderr, 2303*3048Samaguire gettext("%1$s: %2$s: invalid entry on line %3$d\n"), 2304*3048Samaguire myname, RA_CONF_FILE, lineno); 2305*3048Samaguire continue; 2306*3048Samaguire } 2307*3048Samaguire 2308*3048Samaguire if ((raopt = ra_str2opt(confstr)) != NULL) { 2309*3048Samaguire if (ra_parseopt(confstr, lineno, raopt) != 0) { 2310*3048Samaguire (void) fclose(fp); 2311*3048Samaguire return (-1); 2312*3048Samaguire } 2313*3048Samaguire } else if ((ravar = ra_str2var(confstr)) != NULL) { 2314*3048Samaguire if (ra_parsevar(confstr, ravar) != 0) { 2315*3048Samaguire (void) fclose(fp); 2316*3048Samaguire return (-1); 2317*3048Samaguire } 2318*3048Samaguire } else { 2319*3048Samaguire (void) fprintf(stderr, 2320*3048Samaguire gettext("%1$s: %2$s: invalid option name on " 2321*3048Samaguire "line %3$d\n"), 2322*3048Samaguire myname, RA_CONF_FILE, lineno); 2323*3048Samaguire continue; 2324*3048Samaguire } 2325*3048Samaguire } 2326*3048Samaguire 2327*3048Samaguire (void) fclose(fp); 2328*3048Samaguire 2329*3048Samaguire return (1); 2330*3048Samaguire } 2331*3048Samaguire 2332*3048Samaguire static int 2333*3048Samaguire ra_parseopt(char *confstr, int lineno, raopt_t *raopt) 2334*3048Samaguire { 2335*3048Samaguire oval_t oval, d_oval; 2336*3048Samaguire 2337*3048Samaguire if ((confstr = strtok(NULL, " ")) == NULL) { 2338*3048Samaguire (void) fprintf(stderr, 2339*3048Samaguire gettext("%1$s: %2$s: missing value on line %3$d\n"), 2340*3048Samaguire myname, RA_CONF_FILE, lineno); 2341*3048Samaguire return (0); 2342*3048Samaguire } 2343*3048Samaguire if ((oval = ra_str2oval(confstr)) == OPT_INVALID) { 2344*3048Samaguire (void) fprintf(stderr, 2345*3048Samaguire gettext("%1$s: %2$s: invalid option " 2346*3048Samaguire "value on line %3$d\n"), 2347*3048Samaguire myname, RA_CONF_FILE, lineno); 2348*3048Samaguire return (0); 2349*3048Samaguire } 2350*3048Samaguire if (oval != OPT_DEFAULT) 2351*3048Samaguire raopt->opt_enabled = oval == OPT_ENABLED; 2352*3048Samaguire 2353*3048Samaguire if ((confstr = strtok(NULL, " ")) == NULL) { 2354*3048Samaguire (void) fprintf(stderr, 2355*3048Samaguire gettext("%1$s: %2$s: missing revert " 2356*3048Samaguire "value on line %3$d\n"), 2357*3048Samaguire myname, RA_CONF_FILE, lineno); 2358*3048Samaguire return (0); 2359*3048Samaguire } 2360*3048Samaguire if ((d_oval = ra_str2oval(confstr)) == OPT_INVALID) { 2361*3048Samaguire (void) fprintf(stderr, 2362*3048Samaguire gettext("%1$s: %2$s: invalid revert " 2363*3048Samaguire "value on line %3$d\n"), 2364*3048Samaguire myname, RA_CONF_FILE, lineno, confstr); 2365*3048Samaguire return (0); 2366*3048Samaguire } 2367*3048Samaguire raopt->opt_default_enabled = d_oval == OPT_ENABLED; 2368*3048Samaguire if (oval == OPT_DEFAULT) 2369*3048Samaguire raopt->opt_enabled = d_oval == OPT_ENABLED; 2370*3048Samaguire return (0); 2371*3048Samaguire } 2372*3048Samaguire 2373*3048Samaguire static int 2374*3048Samaguire ra_parsevar(char *confstr, ravar_t *ravar) 2375*3048Samaguire { 2376*3048Samaguire confstr = strtok(NULL, "="); 2377*3048Samaguire if (confstr == NULL) { 2378*3048Samaguire /* 2379*3048Samaguire * This isn't an error condition, it simply means that the 2380*3048Samaguire * variable has no value. 2381*3048Samaguire */ 2382*3048Samaguire ravar->var_value = NULL; 2383*3048Samaguire return (0); 2384*3048Samaguire } 2385*3048Samaguire 2386*3048Samaguire if ((ravar->var_value = strdup(confstr)) == NULL) { 2387*3048Samaguire (void) fprintf(stderr, gettext("%s: " 2388*3048Samaguire "unable to allocate memory\n"), myname); 2389*3048Samaguire return (-1); 2390*3048Samaguire } 2391*3048Samaguire return (0); 2392*3048Samaguire } 2393*3048Samaguire 2394*3048Samaguire /* Convert a string to an option value. */ 2395*3048Samaguire static oval_t 2396*3048Samaguire ra_str2oval(const char *valstr) 2397*3048Samaguire { 2398*3048Samaguire if (strcmp(valstr, "enabled") == 0) 2399*3048Samaguire return (OPT_ENABLED); 2400*3048Samaguire else if (strcmp(valstr, "disabled") == 0) 2401*3048Samaguire return (OPT_DISABLED); 2402*3048Samaguire else if (strcmp(valstr, "default") == 0) 2403*3048Samaguire return (OPT_DEFAULT); 2404*3048Samaguire return (OPT_INVALID); 2405*3048Samaguire } 2406*3048Samaguire 2407*3048Samaguire static raopt_t * 2408*3048Samaguire ra_str2opt(const char *optnamestr) 2409*3048Samaguire { 2410*3048Samaguire int i; 2411*3048Samaguire 2412*3048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) { 2413*3048Samaguire if (strcmp(optnamestr, ra_opts[i].opt_name) == 0) 2414*3048Samaguire break; 2415*3048Samaguire } 2416*3048Samaguire if (ra_opts[i].opt_name == NULL) 2417*3048Samaguire return (NULL); 2418*3048Samaguire return (&ra_opts[i]); 2419*3048Samaguire } 2420*3048Samaguire 2421*3048Samaguire /* 2422*3048Samaguire * Reset all option values previously gathered to B_FALSE. 2423*3048Samaguire */ 2424*3048Samaguire static void 2425*3048Samaguire ra_resetopts(void) 2426*3048Samaguire { 2427*3048Samaguire int i; 2428*3048Samaguire 2429*3048Samaguire for (i = 0; ra_opts[i].opt_name != NULL; i++) { 2430*3048Samaguire ra_opts[i].opt_enabled = B_FALSE; 2431*3048Samaguire ra_opts[i].opt_default_enabled = B_FALSE; 2432*3048Samaguire } 2433*3048Samaguire } 2434*3048Samaguire 2435*3048Samaguire static ravar_t * 2436*3048Samaguire ra_str2var(const char *varnamestr) 2437*3048Samaguire { 2438*3048Samaguire int i; 2439*3048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) { 2440*3048Samaguire if (strcmp(varnamestr, ra_vars[i].var_name) == 0) 2441*3048Samaguire break; 2442*3048Samaguire } 2443*3048Samaguire if (ra_vars[i].var_name == NULL) 2444*3048Samaguire return (NULL); 2445*3048Samaguire return (&ra_vars[i]); 2446*3048Samaguire } 2447*3048Samaguire 2448*3048Samaguire /* 2449*3048Samaguire * Reset variable values previously gathered to NULL. 2450*3048Samaguire */ 2451*3048Samaguire static void 2452*3048Samaguire ra_resetvars(const char *proto) 2453*3048Samaguire { 2454*3048Samaguire int i; 2455*3048Samaguire for (i = 0; ra_vars[i].var_name != NULL; i++) { 2456*3048Samaguire if (proto != NULL && 2457*3048Samaguire !VAR_PROTO_MATCH(ra_vars[i].var_name, proto)) 2458*3048Samaguire continue; 2459*3048Samaguire if (ra_vars[i].var_value != NULL) 2460*3048Samaguire free(ra_vars[i].var_value); 2461*3048Samaguire ra_vars[i].var_value = NULL; 2462*3048Samaguire if (ra_vars[i].var_default_value != NULL) 2463*3048Samaguire free(ra_vars[i].var_default_value); 2464*3048Samaguire ra_vars[i].var_default_value = NULL; 2465*3048Samaguire } 2466*3048Samaguire } 2467*3048Samaguire 2468*3048Samaguire /* 2469*3048Samaguire * Given an option name, this function provides an internationalized, human 2470*3048Samaguire * readable version of the option name. 2471*3048Samaguire */ 2472*3048Samaguire static char * 2473*3048Samaguire ra_intloptname(const char *optname) 2474*3048Samaguire { 2475*3048Samaguire if (strcmp(optname, RA_OPT_IPV4_FORWARDING) == 0) 2476*3048Samaguire return (gettext("IPv4 forwarding")); 2477*3048Samaguire else if (strcmp(optname, RA_OPT_IPV4_ROUTING) == 0) 2478*3048Samaguire return (gettext("IPv4 routing")); 2479*3048Samaguire else if (strcmp(optname, RA_OPT_IPV6_FORWARDING) == 0) 2480*3048Samaguire return (gettext("IPv6 forwarding")); 2481*3048Samaguire else if (strcmp(optname, RA_OPT_IPV6_ROUTING) == 0) 2482*3048Samaguire return (gettext("IPv6 routing")); 2483*3048Samaguire else if (strcmp(optname, RA_VAR_IPV4_ROUTING_DAEMON) == 0) 2484*3048Samaguire return (gettext("IPv4 routing daemon")); 2485*3048Samaguire else if (strcmp(optname, RA_VAR_IPV4_ROUTING_DAEMON_ARGS) == 0) 2486*3048Samaguire return (gettext("IPv4 routing daemon args")); 2487*3048Samaguire else if (strcmp(optname, RA_VAR_IPV4_ROUTING_STOP_CMD) == 0) 2488*3048Samaguire return (gettext("IPv4 routing daemon stop")); 2489*3048Samaguire else if (strcmp(optname, RA_VAR_IPV6_ROUTING_DAEMON) == 0) 2490*3048Samaguire return (gettext("IPv6 routing daemon")); 2491*3048Samaguire else if (strcmp(optname, RA_VAR_IPV6_ROUTING_DAEMON_ARGS) == 0) 2492*3048Samaguire return (gettext("IPv6 routing daemon args")); 2493*3048Samaguire else if (strcmp(optname, RA_VAR_IPV6_ROUTING_STOP_CMD) == 0) 2494*3048Samaguire return (gettext("IPv6 routing daemon stop")); 2495*3048Samaguire else if (strcmp(optname, RA_VAR_ROUTING_SVCS) == 0) 2496*3048Samaguire return (gettext("Routing services")); 2497*3048Samaguire /* 2498*3048Samaguire * If we get here, there's a bug and someone should trip over this 2499*3048Samaguire * NULL pointer. 2500*3048Samaguire */ 2501*3048Samaguire return (NULL); 2502*3048Samaguire } 2503