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