17961SNatalie.Li@Sun.COM /* 27961SNatalie.Li@Sun.COM * CDDL HEADER START 37961SNatalie.Li@Sun.COM * 47961SNatalie.Li@Sun.COM * The contents of this file are subject to the terms of the 57961SNatalie.Li@Sun.COM * Common Development and Distribution License (the "License"). 67961SNatalie.Li@Sun.COM * You may not use this file except in compliance with the License. 77961SNatalie.Li@Sun.COM * 87961SNatalie.Li@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97961SNatalie.Li@Sun.COM * or http://www.opensolaris.org/os/licensing. 107961SNatalie.Li@Sun.COM * See the License for the specific language governing permissions 117961SNatalie.Li@Sun.COM * and limitations under the License. 127961SNatalie.Li@Sun.COM * 137961SNatalie.Li@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 147961SNatalie.Li@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157961SNatalie.Li@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 167961SNatalie.Li@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 177961SNatalie.Li@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 187961SNatalie.Li@Sun.COM * 197961SNatalie.Li@Sun.COM * CDDL HEADER END 207961SNatalie.Li@Sun.COM */ 217961SNatalie.Li@Sun.COM /* 228474SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237961SNatalie.Li@Sun.COM * Use is subject to license terms. 247961SNatalie.Li@Sun.COM */ 257961SNatalie.Li@Sun.COM 267961SNatalie.Li@Sun.COM /* 277961SNatalie.Li@Sun.COM * Service Control Manager (SCM) for SVCCTL service. 287961SNatalie.Li@Sun.COM * 297961SNatalie.Li@Sun.COM * This routine maintains a list of SMF service and their states. A list 307961SNatalie.Li@Sun.COM * of Solaris SMF service are displayed on the Server/Connection Manager 317961SNatalie.Li@Sun.COM * Windows client. 327961SNatalie.Li@Sun.COM */ 337961SNatalie.Li@Sun.COM #include <stdio.h> 347961SNatalie.Li@Sun.COM #include <stdlib.h> 357961SNatalie.Li@Sun.COM #include <stdarg.h> 367961SNatalie.Li@Sun.COM #include <strings.h> 377961SNatalie.Li@Sun.COM #include <assert.h> 387961SNatalie.Li@Sun.COM #include <errno.h> 397961SNatalie.Li@Sun.COM #include <libscf.h> 407961SNatalie.Li@Sun.COM #include <libscf_priv.h> 417961SNatalie.Li@Sun.COM #include <time.h> 42*10122SJordan.Brown@Sun.COM #include <dlfcn.h> 437961SNatalie.Li@Sun.COM #include <sys/types.h> 44*10122SJordan.Brown@Sun.COM #include <smbsrv/winsvc.h> 45*10122SJordan.Brown@Sun.COM #include <smbsrv/nterror.h> 46*10122SJordan.Brown@Sun.COM #include <smbsrv/ndl/svcctl.ndl> 47*10122SJordan.Brown@Sun.COM #include <smbsrv/libmlsvc.h> 487961SNatalie.Li@Sun.COM 497961SNatalie.Li@Sun.COM #define LEGACY_UNKNOWN "unknown" 507961SNatalie.Li@Sun.COM #define SVC_NAME_PROP "name" 517961SNatalie.Li@Sun.COM 527961SNatalie.Li@Sun.COM /* Flags for svcctl_scm_pg_get_val() */ 537961SNatalie.Li@Sun.COM #define EMPTY_OK 0x01 547961SNatalie.Li@Sun.COM #define MULTI_OK 0x02 557961SNatalie.Li@Sun.COM 56*10122SJordan.Brown@Sun.COM static void *svcctl_scm_interposer_hdl = NULL; 57*10122SJordan.Brown@Sun.COM static struct { 58*10122SJordan.Brown@Sun.COM int (*svcctl_op_scm_init)(svcctl_manager_context_t *); 59*10122SJordan.Brown@Sun.COM int (*svcctl_op_scf_init)(svcctl_manager_context_t *); 60*10122SJordan.Brown@Sun.COM } svcctl_scm_ops; 61*10122SJordan.Brown@Sun.COM 627961SNatalie.Li@Sun.COM /* 637961SNatalie.Li@Sun.COM * svcctl_scm_avl_nodecmp 647961SNatalie.Li@Sun.COM * 657961SNatalie.Li@Sun.COM * Comparision function for nodes in an AVL tree of services. 667961SNatalie.Li@Sun.COM */ 677961SNatalie.Li@Sun.COM /* ARGSUSED */ 687961SNatalie.Li@Sun.COM static int 697961SNatalie.Li@Sun.COM svcctl_scm_avl_nodecmp(const void *l_arg, const void *r_arg, void *m_name_len) 707961SNatalie.Li@Sun.COM { 717961SNatalie.Li@Sun.COM const svcctl_svc_node_t *l = l_arg; 727961SNatalie.Li@Sun.COM const svcctl_svc_node_t *r = r_arg; 737961SNatalie.Li@Sun.COM int *max_name_len = m_name_len; 747961SNatalie.Li@Sun.COM int ret = 0; 757961SNatalie.Li@Sun.COM 767961SNatalie.Li@Sun.COM ret = strncasecmp(l->sn_name, r->sn_name, *max_name_len); 777961SNatalie.Li@Sun.COM 787961SNatalie.Li@Sun.COM if (ret > 0) 797961SNatalie.Li@Sun.COM return (1); 807961SNatalie.Li@Sun.COM if (ret < 0) 817961SNatalie.Li@Sun.COM return (-1); 827961SNatalie.Li@Sun.COM return (0); 837961SNatalie.Li@Sun.COM } 847961SNatalie.Li@Sun.COM 857961SNatalie.Li@Sun.COM /* 867961SNatalie.Li@Sun.COM * svcctl_scm_pg_get_val 877961SNatalie.Li@Sun.COM * 887961SNatalie.Li@Sun.COM * Get the single value of the named property in the given property group, 897961SNatalie.Li@Sun.COM * which must have type ty, and put it in *vp. If ty is SCF_TYPE_ASTRING, vp 907961SNatalie.Li@Sun.COM * is taken to be a char **, and sz is the size of the buffer. sz is unused 917961SNatalie.Li@Sun.COM * otherwise. Return 0 on success, -1 if the property doesn't exist, has the 927961SNatalie.Li@Sun.COM * wrong type, or doesn't have a single value. If flags has EMPTY_OK, don't 937961SNatalie.Li@Sun.COM * complain if the property has no values (but return nonzero). If flags has 947961SNatalie.Li@Sun.COM * MULTI_OK and the property has multiple values, succeed with E2BIG. 957961SNatalie.Li@Sun.COM */ 967961SNatalie.Li@Sun.COM static int 977961SNatalie.Li@Sun.COM svcctl_scm_pg_get_val(svcctl_manager_context_t *mgr_ctx, 987961SNatalie.Li@Sun.COM scf_propertygroup_t *pg, const char *propname, scf_type_t ty, void *vp, 997961SNatalie.Li@Sun.COM size_t sz, uint_t flags) 1007961SNatalie.Li@Sun.COM { 1017961SNatalie.Li@Sun.COM int ret = -1, r; 1027961SNatalie.Li@Sun.COM boolean_t multi = B_FALSE; 1037961SNatalie.Li@Sun.COM 1047961SNatalie.Li@Sun.COM assert((flags & ~(EMPTY_OK | MULTI_OK)) == 0); 1057961SNatalie.Li@Sun.COM 1067961SNatalie.Li@Sun.COM if (scf_pg_get_property(pg, propname, mgr_ctx->mc_scf_gprop) == -1) 1077961SNatalie.Li@Sun.COM return (ret); 1087961SNatalie.Li@Sun.COM 1097961SNatalie.Li@Sun.COM if (scf_property_is_type(mgr_ctx->mc_scf_gprop, ty) != SCF_SUCCESS) 1107961SNatalie.Li@Sun.COM return (ret); 1117961SNatalie.Li@Sun.COM 1127961SNatalie.Li@Sun.COM if (scf_property_get_value(mgr_ctx->mc_scf_gprop, 1137961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gval) != SCF_SUCCESS) { 1147961SNatalie.Li@Sun.COM switch (scf_error()) { 1157961SNatalie.Li@Sun.COM case SCF_ERROR_NOT_FOUND: 1167961SNatalie.Li@Sun.COM return (ret); 1177961SNatalie.Li@Sun.COM 1187961SNatalie.Li@Sun.COM case SCF_ERROR_CONSTRAINT_VIOLATED: 1197961SNatalie.Li@Sun.COM if (flags & MULTI_OK) { 1207961SNatalie.Li@Sun.COM multi = B_TRUE; 1217961SNatalie.Li@Sun.COM break; 1227961SNatalie.Li@Sun.COM } 1237961SNatalie.Li@Sun.COM return (ret); 1247961SNatalie.Li@Sun.COM 1257961SNatalie.Li@Sun.COM case SCF_ERROR_PERMISSION_DENIED: 1267961SNatalie.Li@Sun.COM default: 1277961SNatalie.Li@Sun.COM return (ret); 1287961SNatalie.Li@Sun.COM } 1297961SNatalie.Li@Sun.COM } 1307961SNatalie.Li@Sun.COM 1317961SNatalie.Li@Sun.COM switch (ty) { 1327961SNatalie.Li@Sun.COM case SCF_TYPE_ASTRING: 1337961SNatalie.Li@Sun.COM r = scf_value_get_astring 1347961SNatalie.Li@Sun.COM (mgr_ctx->mc_scf_gval, vp, sz) > 0 ? SCF_SUCCESS : -1; 1357961SNatalie.Li@Sun.COM break; 1367961SNatalie.Li@Sun.COM 1377961SNatalie.Li@Sun.COM case SCF_TYPE_BOOLEAN: 1387961SNatalie.Li@Sun.COM r = scf_value_get_boolean(mgr_ctx->mc_scf_gval, (uint8_t *)vp); 1397961SNatalie.Li@Sun.COM break; 1407961SNatalie.Li@Sun.COM 1417961SNatalie.Li@Sun.COM case SCF_TYPE_COUNT: 1427961SNatalie.Li@Sun.COM r = scf_value_get_count(mgr_ctx->mc_scf_gval, (uint64_t *)vp); 1437961SNatalie.Li@Sun.COM break; 1447961SNatalie.Li@Sun.COM 1457961SNatalie.Li@Sun.COM case SCF_TYPE_INTEGER: 1467961SNatalie.Li@Sun.COM r = scf_value_get_integer(mgr_ctx->mc_scf_gval, (int64_t *)vp); 1477961SNatalie.Li@Sun.COM break; 1487961SNatalie.Li@Sun.COM 1497961SNatalie.Li@Sun.COM case SCF_TYPE_TIME: { 1507961SNatalie.Li@Sun.COM int64_t sec; 1517961SNatalie.Li@Sun.COM int32_t ns; 1527961SNatalie.Li@Sun.COM r = scf_value_get_time(mgr_ctx->mc_scf_gval, &sec, &ns); 1537961SNatalie.Li@Sun.COM ((struct timeval *)vp)->tv_sec = sec; 1547961SNatalie.Li@Sun.COM ((struct timeval *)vp)->tv_usec = ns / 1000; 1557961SNatalie.Li@Sun.COM break; 1567961SNatalie.Li@Sun.COM } 1577961SNatalie.Li@Sun.COM 1587961SNatalie.Li@Sun.COM case SCF_TYPE_USTRING: 1597961SNatalie.Li@Sun.COM r = scf_value_get_ustring(mgr_ctx->mc_scf_gval, vp, sz) > 0 ? 1607961SNatalie.Li@Sun.COM SCF_SUCCESS : -1; 1617961SNatalie.Li@Sun.COM break; 1627961SNatalie.Li@Sun.COM 1637961SNatalie.Li@Sun.COM default: 1647961SNatalie.Li@Sun.COM return (ret); 1657961SNatalie.Li@Sun.COM } 1667961SNatalie.Li@Sun.COM 1677961SNatalie.Li@Sun.COM if (r != SCF_SUCCESS) 1687961SNatalie.Li@Sun.COM return (ret); 1697961SNatalie.Li@Sun.COM 1707961SNatalie.Li@Sun.COM ret = multi ? E2BIG : 0; 1717961SNatalie.Li@Sun.COM 1727961SNatalie.Li@Sun.COM return (ret); 1737961SNatalie.Li@Sun.COM } 1747961SNatalie.Li@Sun.COM 1757961SNatalie.Li@Sun.COM /* 1767961SNatalie.Li@Sun.COM * svcctl_scm_get_running_snapshot 1777961SNatalie.Li@Sun.COM * 1787961SNatalie.Li@Sun.COM * Get running snapshot of a service instance. 1797961SNatalie.Li@Sun.COM */ 1807961SNatalie.Li@Sun.COM static scf_snapshot_t * 1817961SNatalie.Li@Sun.COM svcctl_scm_get_running_snapshot(svcctl_manager_context_t *mgr_ctx, 1827961SNatalie.Li@Sun.COM scf_instance_t *inst) 1837961SNatalie.Li@Sun.COM { 1847961SNatalie.Li@Sun.COM scf_snapshot_t *snap; 1857961SNatalie.Li@Sun.COM 1867961SNatalie.Li@Sun.COM snap = scf_snapshot_create(mgr_ctx->mc_scf_hdl); 1877961SNatalie.Li@Sun.COM if (snap == NULL) 1887961SNatalie.Li@Sun.COM return (NULL); 1897961SNatalie.Li@Sun.COM 1907961SNatalie.Li@Sun.COM if (scf_instance_get_snapshot(inst, "running", snap) == 0) 1917961SNatalie.Li@Sun.COM return (snap); 1927961SNatalie.Li@Sun.COM 1937961SNatalie.Li@Sun.COM if (scf_error() != SCF_ERROR_NOT_FOUND) 1947961SNatalie.Li@Sun.COM return (NULL); 1957961SNatalie.Li@Sun.COM 1967961SNatalie.Li@Sun.COM scf_snapshot_destroy(snap); 1977961SNatalie.Li@Sun.COM return (NULL); 1987961SNatalie.Li@Sun.COM } 1997961SNatalie.Li@Sun.COM 2007961SNatalie.Li@Sun.COM /* 2017961SNatalie.Li@Sun.COM * svcctl_scm_inst_get_val 2027961SNatalie.Li@Sun.COM * 2037961SNatalie.Li@Sun.COM * As svcctl_scm_pg_get_val(), except look the property group up in an 2047961SNatalie.Li@Sun.COM * instance. If "use_running" is set, and the running snapshot exists, 2057961SNatalie.Li@Sun.COM * do a composed lookup there. Otherwise, do an (optionally composed) 2067961SNatalie.Li@Sun.COM * lookup on the current values. Note that lookups using snapshots are 2077961SNatalie.Li@Sun.COM * always composed. 2087961SNatalie.Li@Sun.COM */ 2097961SNatalie.Li@Sun.COM static int 2107961SNatalie.Li@Sun.COM svcctl_scm_inst_get_val(svcctl_manager_context_t *mgr_ctx, scf_instance_t *inst, 2117961SNatalie.Li@Sun.COM const char *pgname, const char *propname, scf_type_t ty, void *vp, 2127961SNatalie.Li@Sun.COM size_t sz, uint_t flags, int use_running, int composed) 2137961SNatalie.Li@Sun.COM { 2147961SNatalie.Li@Sun.COM scf_snapshot_t *snap = NULL; 2157961SNatalie.Li@Sun.COM int r; 2167961SNatalie.Li@Sun.COM 2177961SNatalie.Li@Sun.COM if (use_running) 2187961SNatalie.Li@Sun.COM snap = svcctl_scm_get_running_snapshot(mgr_ctx, inst); 2197961SNatalie.Li@Sun.COM if (composed || use_running) 2207961SNatalie.Li@Sun.COM r = scf_instance_get_pg_composed(inst, snap, pgname, 2217961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gpg); 2227961SNatalie.Li@Sun.COM else 2237961SNatalie.Li@Sun.COM r = scf_instance_get_pg(inst, pgname, mgr_ctx->mc_scf_gpg); 2247961SNatalie.Li@Sun.COM if (snap) 2257961SNatalie.Li@Sun.COM scf_snapshot_destroy(snap); 2267961SNatalie.Li@Sun.COM if (r == -1) 2277961SNatalie.Li@Sun.COM return (-1); 2287961SNatalie.Li@Sun.COM 2297961SNatalie.Li@Sun.COM r = svcctl_scm_pg_get_val(mgr_ctx, mgr_ctx->mc_scf_gpg, propname, ty, 2307961SNatalie.Li@Sun.COM vp, sz, flags); 2317961SNatalie.Li@Sun.COM 2327961SNatalie.Li@Sun.COM return (r); 2337961SNatalie.Li@Sun.COM } 2347961SNatalie.Li@Sun.COM 2357961SNatalie.Li@Sun.COM /* 2367961SNatalie.Li@Sun.COM * svcctl_scm_get_restarter_string_prop 2377961SNatalie.Li@Sun.COM * 2387961SNatalie.Li@Sun.COM * Get a string property from the restarter property group of the given 2397961SNatalie.Li@Sun.COM * instance. Return an empty string on normal problems. 2407961SNatalie.Li@Sun.COM */ 2417961SNatalie.Li@Sun.COM static void 2427961SNatalie.Li@Sun.COM svcctl_scm_get_restarter_string_prop(svcctl_manager_context_t *mgr_ctx, 2437961SNatalie.Li@Sun.COM scf_instance_t *inst, const char *pname, char *buf, size_t buf_sz) 2447961SNatalie.Li@Sun.COM { 2457961SNatalie.Li@Sun.COM if (svcctl_scm_inst_get_val(mgr_ctx, inst, SCF_PG_RESTARTER, pname, 2467961SNatalie.Li@Sun.COM SCF_TYPE_ASTRING, buf, buf_sz, 0, 0, 1) != 0) 2477961SNatalie.Li@Sun.COM *buf = '\0'; 2487961SNatalie.Li@Sun.COM } 2497961SNatalie.Li@Sun.COM 2507961SNatalie.Li@Sun.COM /* 2517961SNatalie.Li@Sun.COM * svcctl_scm_svc_transitioning 2527961SNatalie.Li@Sun.COM * 2537961SNatalie.Li@Sun.COM * Return true if a service instance is transitioning. 2547961SNatalie.Li@Sun.COM */ 2557961SNatalie.Li@Sun.COM static int 2567961SNatalie.Li@Sun.COM svcctl_scm_svc_transitioning(svcctl_manager_context_t *mgr_ctx, 2577961SNatalie.Li@Sun.COM scf_instance_t *inst) 2587961SNatalie.Li@Sun.COM { 2597961SNatalie.Li@Sun.COM char nstate_name[MAX_SCF_STATE_STRING_SZ]; 2607961SNatalie.Li@Sun.COM 2617961SNatalie.Li@Sun.COM bzero(nstate_name, MAX_SCF_STATE_STRING_SZ); 2627961SNatalie.Li@Sun.COM svcctl_scm_get_restarter_string_prop(mgr_ctx, inst, 2637961SNatalie.Li@Sun.COM SCF_PROPERTY_NEXT_STATE, nstate_name, sizeof (nstate_name)); 2647961SNatalie.Li@Sun.COM 2657961SNatalie.Li@Sun.COM return ((*nstate_name == '\0')); 2667961SNatalie.Li@Sun.COM } 2677961SNatalie.Li@Sun.COM 2687961SNatalie.Li@Sun.COM /* 2697961SNatalie.Li@Sun.COM * svcctl_scm_get_svcstate 2707961SNatalie.Li@Sun.COM * 2717961SNatalie.Li@Sun.COM * Gets the state of an SMF service. 2727961SNatalie.Li@Sun.COM */ 2737961SNatalie.Li@Sun.COM static int 2747961SNatalie.Li@Sun.COM svcctl_scm_get_svcstate(svcctl_manager_context_t *mgr_ctx, 2757961SNatalie.Li@Sun.COM char **buf, scf_walkinfo_t *wip) 2767961SNatalie.Li@Sun.COM { 2777961SNatalie.Li@Sun.COM char *state_name; 2787961SNatalie.Li@Sun.COM size_t max_state_size; 2797961SNatalie.Li@Sun.COM 2807961SNatalie.Li@Sun.COM max_state_size = MAX_SCF_STATE_STRING_SZ + 1; 2817961SNatalie.Li@Sun.COM 2827961SNatalie.Li@Sun.COM if ((state_name = malloc(max_state_size)) == NULL) 2837961SNatalie.Li@Sun.COM return (-1); 2847961SNatalie.Li@Sun.COM 2857961SNatalie.Li@Sun.COM if (wip->pg == NULL) { 2867961SNatalie.Li@Sun.COM svcctl_scm_get_restarter_string_prop(mgr_ctx, wip->inst, 2877961SNatalie.Li@Sun.COM SCF_PROPERTY_STATE, state_name, max_state_size); 2887961SNatalie.Li@Sun.COM 2897961SNatalie.Li@Sun.COM /* Don't print blank fields, to ease parsing. */ 2907961SNatalie.Li@Sun.COM if (state_name[0] == '\0') { 2917961SNatalie.Li@Sun.COM state_name[0] = '-'; 2927961SNatalie.Li@Sun.COM state_name[1] = '\0'; 2937961SNatalie.Li@Sun.COM } 2947961SNatalie.Li@Sun.COM 2957961SNatalie.Li@Sun.COM if (svcctl_scm_svc_transitioning(mgr_ctx, wip->inst)) 2967961SNatalie.Li@Sun.COM /* Append an asterisk if new state is valid. */ 2977961SNatalie.Li@Sun.COM (void) strlcat(state_name, "*", max_state_size); 2987961SNatalie.Li@Sun.COM 2997961SNatalie.Li@Sun.COM } else 3007961SNatalie.Li@Sun.COM (void) strlcpy(state_name, SCF_STATE_STRING_LEGACY, 3017961SNatalie.Li@Sun.COM max_state_size); 3027961SNatalie.Li@Sun.COM 3037961SNatalie.Li@Sun.COM *buf = state_name; 3047961SNatalie.Li@Sun.COM return (0); 3057961SNatalie.Li@Sun.COM } 3067961SNatalie.Li@Sun.COM 3077961SNatalie.Li@Sun.COM /* 3087961SNatalie.Li@Sun.COM * svcctl_scm_get_svcdesc 3097961SNatalie.Li@Sun.COM * 3107961SNatalie.Li@Sun.COM * Gets the description of an SMF service. 3117961SNatalie.Li@Sun.COM */ 3127961SNatalie.Li@Sun.COM static int 3137961SNatalie.Li@Sun.COM svcctl_scm_get_svcdesc(svcctl_manager_context_t *mgr_ctx, 3147961SNatalie.Li@Sun.COM char **buf, scf_walkinfo_t *wip) 3157961SNatalie.Li@Sun.COM { 3167961SNatalie.Li@Sun.COM char *x; 3177961SNatalie.Li@Sun.COM size_t newsize; 3187961SNatalie.Li@Sun.COM char *newbuf; 3197961SNatalie.Li@Sun.COM char *desc_buf = NULL; 3207961SNatalie.Li@Sun.COM 3217961SNatalie.Li@Sun.COM if ((desc_buf = malloc(mgr_ctx->mc_scf_max_value_len + 1)) == NULL) 3227961SNatalie.Li@Sun.COM return (-1); 3237961SNatalie.Li@Sun.COM 3247961SNatalie.Li@Sun.COM bzero(desc_buf, mgr_ctx->mc_scf_max_value_len + 1); 3257961SNatalie.Li@Sun.COM if (wip->pg != NULL) 3267961SNatalie.Li@Sun.COM desc_buf[0] = '-'; 3277961SNatalie.Li@Sun.COM else if (svcctl_scm_inst_get_val(mgr_ctx, wip->inst, 3287961SNatalie.Li@Sun.COM SCF_PG_TM_COMMON_NAME, "C", SCF_TYPE_USTRING, desc_buf, 3297961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_value_len, 0, 1, 1) == -1) 3307961SNatalie.Li@Sun.COM desc_buf[0] = '-'; 3317961SNatalie.Li@Sun.COM 3327961SNatalie.Li@Sun.COM /* 3337961SNatalie.Li@Sun.COM * Collapse multi-line tm_common_name values into a single line. 3347961SNatalie.Li@Sun.COM */ 3357961SNatalie.Li@Sun.COM for (x = desc_buf; *x != '\0'; x++) 3367961SNatalie.Li@Sun.COM if (*x == '\n') 3377961SNatalie.Li@Sun.COM *x = ' '; 3387961SNatalie.Li@Sun.COM 3397961SNatalie.Li@Sun.COM newsize = strlen(desc_buf) + 1; 3407961SNatalie.Li@Sun.COM if ((newbuf = malloc(newsize)) == NULL) { 3417961SNatalie.Li@Sun.COM free(desc_buf); 3427961SNatalie.Li@Sun.COM return (-1); 3437961SNatalie.Li@Sun.COM } 3447961SNatalie.Li@Sun.COM 3457961SNatalie.Li@Sun.COM (void) snprintf(newbuf, newsize, "%s", desc_buf); 3467961SNatalie.Li@Sun.COM free(desc_buf); 3477961SNatalie.Li@Sun.COM 3487961SNatalie.Li@Sun.COM *buf = newbuf; 3497961SNatalie.Li@Sun.COM return (0); 3507961SNatalie.Li@Sun.COM } 3517961SNatalie.Li@Sun.COM 3527961SNatalie.Li@Sun.COM /* 3537961SNatalie.Li@Sun.COM * svcctl_scm_get_svcfmri 3547961SNatalie.Li@Sun.COM * 3557961SNatalie.Li@Sun.COM * Gets the FMRI of an SMF service. 3567961SNatalie.Li@Sun.COM */ 3577961SNatalie.Li@Sun.COM static int 3587961SNatalie.Li@Sun.COM svcctl_scm_get_svcfmri(svcctl_manager_context_t *mgr_ctx, 3597961SNatalie.Li@Sun.COM char **buf, scf_walkinfo_t *wip) 3607961SNatalie.Li@Sun.COM { 3617961SNatalie.Li@Sun.COM size_t newsize; 3627961SNatalie.Li@Sun.COM char *newbuf; 3637961SNatalie.Li@Sun.COM char *fmri_buf = NULL; 3647961SNatalie.Li@Sun.COM void *fmri_p = NULL; 3657961SNatalie.Li@Sun.COM size_t fmri_size; 3667961SNatalie.Li@Sun.COM 3677961SNatalie.Li@Sun.COM if ((fmri_buf = malloc(mgr_ctx->mc_scf_max_fmri_len + 1)) == NULL) 3687961SNatalie.Li@Sun.COM return (-1); 3697961SNatalie.Li@Sun.COM 3707961SNatalie.Li@Sun.COM if (wip->pg == NULL) { 3717961SNatalie.Li@Sun.COM if (scf_instance_to_fmri(wip->inst, fmri_buf, 3727961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_fmri_len + 1) == -1) { 3737961SNatalie.Li@Sun.COM free(fmri_buf); 3747961SNatalie.Li@Sun.COM return (-1); 3757961SNatalie.Li@Sun.COM } 3767961SNatalie.Li@Sun.COM } else { 3777961SNatalie.Li@Sun.COM (void) strlcpy(fmri_buf, SCF_FMRI_LEGACY_PREFIX, 3787961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_fmri_len + 1); 3797961SNatalie.Li@Sun.COM 3807961SNatalie.Li@Sun.COM fmri_p = fmri_buf + sizeof (SCF_FMRI_LEGACY_PREFIX) - 1; 3817961SNatalie.Li@Sun.COM fmri_size = mgr_ctx->mc_scf_max_fmri_len + 1 - \ 3827961SNatalie.Li@Sun.COM (sizeof (SCF_FMRI_LEGACY_PREFIX) - 1); 3837961SNatalie.Li@Sun.COM 3847961SNatalie.Li@Sun.COM if (svcctl_scm_pg_get_val(mgr_ctx, wip->pg, 3857961SNatalie.Li@Sun.COM SCF_LEGACY_PROPERTY_NAME, SCF_TYPE_ASTRING, 3867961SNatalie.Li@Sun.COM fmri_p, fmri_size, 0) != 0) 3877961SNatalie.Li@Sun.COM (void) strlcat(fmri_buf, LEGACY_UNKNOWN, 3887961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_fmri_len + 1); 3897961SNatalie.Li@Sun.COM } 3907961SNatalie.Li@Sun.COM 3917961SNatalie.Li@Sun.COM newsize = strlen(fmri_buf) + 1; 3927961SNatalie.Li@Sun.COM if ((newbuf = malloc(newsize)) == NULL) { 3937961SNatalie.Li@Sun.COM free(fmri_buf); 3947961SNatalie.Li@Sun.COM return (-1); 3957961SNatalie.Li@Sun.COM } 3967961SNatalie.Li@Sun.COM 3977961SNatalie.Li@Sun.COM (void) snprintf(newbuf, newsize, "%s", fmri_buf); 3987961SNatalie.Li@Sun.COM free(fmri_buf); 3997961SNatalie.Li@Sun.COM 4007961SNatalie.Li@Sun.COM *buf = newbuf; 4017961SNatalie.Li@Sun.COM return (0); 4027961SNatalie.Li@Sun.COM } 4037961SNatalie.Li@Sun.COM 4047961SNatalie.Li@Sun.COM /* 4057961SNatalie.Li@Sun.COM * svcctl_scm_get_svcname 4067961SNatalie.Li@Sun.COM * 4077961SNatalie.Li@Sun.COM * Gets the FMRI of an SMF service. 4087961SNatalie.Li@Sun.COM */ 4097961SNatalie.Li@Sun.COM static int 4107961SNatalie.Li@Sun.COM svcctl_scm_get_svcname(char **buf, char *fmri) 4117961SNatalie.Li@Sun.COM { 4127961SNatalie.Li@Sun.COM char *nm_buf = NULL; 4137961SNatalie.Li@Sun.COM char *newbuf; 4147961SNatalie.Li@Sun.COM size_t newsize; 4157961SNatalie.Li@Sun.COM 4167961SNatalie.Li@Sun.COM if (fmri == NULL) 4177961SNatalie.Li@Sun.COM return (-1); 4187961SNatalie.Li@Sun.COM 4197961SNatalie.Li@Sun.COM newsize = strlen(fmri); 4207961SNatalie.Li@Sun.COM if ((newbuf = malloc(newsize)) == NULL) 4217961SNatalie.Li@Sun.COM return (-1); 4227961SNatalie.Li@Sun.COM 4237961SNatalie.Li@Sun.COM if ((nm_buf = strchr(fmri, '/')) == NULL) 4247961SNatalie.Li@Sun.COM return (-1); 4257961SNatalie.Li@Sun.COM 4267961SNatalie.Li@Sun.COM (void) snprintf(newbuf, newsize, "%s", ++nm_buf); 4277961SNatalie.Li@Sun.COM *buf = newbuf; 4287961SNatalie.Li@Sun.COM return (0); 4297961SNatalie.Li@Sun.COM } 4307961SNatalie.Li@Sun.COM 4317961SNatalie.Li@Sun.COM /* 4327961SNatalie.Li@Sun.COM * svcctl_scm_cb_list_svcinst 4337961SNatalie.Li@Sun.COM * 4347961SNatalie.Li@Sun.COM * Callback function to walk all the services in an SCF repository. 4357961SNatalie.Li@Sun.COM */ 4367961SNatalie.Li@Sun.COM static int 4377961SNatalie.Li@Sun.COM svcctl_scm_cb_list_svcinst(void *context, scf_walkinfo_t *wip) 4387961SNatalie.Li@Sun.COM { 4397961SNatalie.Li@Sun.COM svcctl_svc_node_t *node = NULL; 4407961SNatalie.Li@Sun.COM uu_avl_index_t idx; 4417961SNatalie.Li@Sun.COM svcctl_manager_context_t *mgr_ctx = (svcctl_manager_context_t *)context; 4427961SNatalie.Li@Sun.COM 4437961SNatalie.Li@Sun.COM node = malloc(sizeof (*node)); 4447961SNatalie.Li@Sun.COM if (node == NULL) 4457961SNatalie.Li@Sun.COM return (-1); 4467961SNatalie.Li@Sun.COM 4477961SNatalie.Li@Sun.COM node->sn_fmri = NULL; 4487961SNatalie.Li@Sun.COM if (svcctl_scm_get_svcfmri(mgr_ctx, &node->sn_fmri, wip) != 0) 4497961SNatalie.Li@Sun.COM return (-1); 4507961SNatalie.Li@Sun.COM 4517961SNatalie.Li@Sun.COM node->sn_name = NULL; 4527961SNatalie.Li@Sun.COM if (svcctl_scm_get_svcname(&node->sn_name, node->sn_fmri) != 0) 4537961SNatalie.Li@Sun.COM return (-1); 4547961SNatalie.Li@Sun.COM 4557961SNatalie.Li@Sun.COM node->sn_desc = NULL; 4567961SNatalie.Li@Sun.COM if (svcctl_scm_get_svcdesc(mgr_ctx, &node->sn_desc, wip) != 0) 4577961SNatalie.Li@Sun.COM return (-1); 4587961SNatalie.Li@Sun.COM 4597961SNatalie.Li@Sun.COM node->sn_state = NULL; 4607961SNatalie.Li@Sun.COM if (svcctl_scm_get_svcstate(mgr_ctx, &node->sn_state, wip) != 0) 4617961SNatalie.Li@Sun.COM return (-1); 4627961SNatalie.Li@Sun.COM 4637961SNatalie.Li@Sun.COM /* Insert into AVL tree. */ 4647961SNatalie.Li@Sun.COM uu_avl_node_init(node, &node->sn_node, mgr_ctx->mc_svcs_pool); 4657961SNatalie.Li@Sun.COM (void) uu_avl_find(mgr_ctx->mc_svcs, node, 4667961SNatalie.Li@Sun.COM &mgr_ctx->mc_scf_max_fmri_len, &idx); 4677961SNatalie.Li@Sun.COM uu_avl_insert(mgr_ctx->mc_svcs, node, idx); 4687961SNatalie.Li@Sun.COM 4697961SNatalie.Li@Sun.COM return (0); 4707961SNatalie.Li@Sun.COM } 4717961SNatalie.Li@Sun.COM 4727961SNatalie.Li@Sun.COM /* 4737961SNatalie.Li@Sun.COM * svcctl_scm_map_status 4747961SNatalie.Li@Sun.COM * 4757961SNatalie.Li@Sun.COM * Report the service status. 4767961SNatalie.Li@Sun.COM * 4777961SNatalie.Li@Sun.COM * The mapping between the Microsoft service states and SMF service states 4787961SNatalie.Li@Sun.COM * are as follows. 4797961SNatalie.Li@Sun.COM * 4807961SNatalie.Li@Sun.COM * SMF service states 4817961SNatalie.Li@Sun.COM * ================== 4827961SNatalie.Li@Sun.COM * SCF_STATE_UNINIT 0x00000001 4837961SNatalie.Li@Sun.COM * SCF_STATE_MAINT 0x00000002 4847961SNatalie.Li@Sun.COM * SCF_STATE_OFFLINE 0x00000004 4857961SNatalie.Li@Sun.COM * SCF_STATE_DISABLED 0x00000008 4867961SNatalie.Li@Sun.COM * SCF_STATE_ONLINE 0x00000010 4877961SNatalie.Li@Sun.COM * SCF_STATE_DEGRADED 0x00000020 4887961SNatalie.Li@Sun.COM * SCF_STATE_ALL 0x0000003F 4897961SNatalie.Li@Sun.COM * 4907961SNatalie.Li@Sun.COM * Microsoft service states 4917961SNatalie.Li@Sun.COM * ======================== 4927961SNatalie.Li@Sun.COM * SERVICE_CONTINUE_PENDING 0x00000005 4937961SNatalie.Li@Sun.COM * SERVICE_PAUSE_PENDING 0x00000006 4947961SNatalie.Li@Sun.COM * SERVICE_PAUSED 0x00000007 4957961SNatalie.Li@Sun.COM * SERVICE_RUNNING 0x00000004 4967961SNatalie.Li@Sun.COM * SERVICE_START_PENDING 0x00000002 4977961SNatalie.Li@Sun.COM * SERVICE_STOP_PENDING 0x00000003 4987961SNatalie.Li@Sun.COM * SERVICE_STOPPED 0x00000001 4997961SNatalie.Li@Sun.COM * 5007961SNatalie.Li@Sun.COM * Mapping 5017961SNatalie.Li@Sun.COM * ======= 5027961SNatalie.Li@Sun.COM * 5037961SNatalie.Li@Sun.COM * SCF_STATE_ONLINE <-> SERVICE_RUNNING 5047961SNatalie.Li@Sun.COM * SCF_STATE_OFFLINE <-> SERVICE_PAUSED 5057961SNatalie.Li@Sun.COM * SCF_STATE_DISABLED <-> SERVICE_STOPPED 5067961SNatalie.Li@Sun.COM * SCF_STATE_UNINIT <-> SERVICE_START_PENDING 5077961SNatalie.Li@Sun.COM * SCF_STATE_DEGRADED <-> SERVICE_STOP_PENDING 5087961SNatalie.Li@Sun.COM * SCF_STATE_MAINT <-> SERVICE_PAUSE_PENDING 5097961SNatalie.Li@Sun.COM * SCF_STATE_STRING_LEGACY <-> SERVICE_RUNNING 5107961SNatalie.Li@Sun.COM * Service Transitioning <-> SERVICE_STOP_PENDING 5117961SNatalie.Li@Sun.COM */ 5127961SNatalie.Li@Sun.COM uint32_t 5137961SNatalie.Li@Sun.COM svcctl_scm_map_status(const char *state) 5147961SNatalie.Li@Sun.COM { 5157961SNatalie.Li@Sun.COM int i; 5167961SNatalie.Li@Sun.COM 5177961SNatalie.Li@Sun.COM struct { 5187961SNatalie.Li@Sun.COM const char *scf_state; 5197961SNatalie.Li@Sun.COM uint32_t scm_state; 5207961SNatalie.Li@Sun.COM } state_map[] = { 5217961SNatalie.Li@Sun.COM { SCF_STATE_STRING_ONLINE, SERVICE_RUNNING }, 5227961SNatalie.Li@Sun.COM { SCF_STATE_STRING_OFFLINE, SERVICE_PAUSED }, 5237961SNatalie.Li@Sun.COM { SCF_STATE_STRING_DISABLED, SERVICE_STOPPED }, 5247961SNatalie.Li@Sun.COM { SCF_STATE_STRING_UNINIT, SERVICE_START_PENDING }, 5257961SNatalie.Li@Sun.COM { SCF_STATE_STRING_DEGRADED, SERVICE_STOP_PENDING }, 5267961SNatalie.Li@Sun.COM { SCF_STATE_STRING_MAINT, SERVICE_PAUSE_PENDING }, 5277961SNatalie.Li@Sun.COM { SCF_STATE_STRING_LEGACY, SERVICE_RUNNING } 5287961SNatalie.Li@Sun.COM }; 5297961SNatalie.Li@Sun.COM 5307961SNatalie.Li@Sun.COM for (i = 0; i < (sizeof (state_map)/sizeof (state_map[0])); ++i) { 5317961SNatalie.Li@Sun.COM if (strcmp(state, state_map[i].scf_state) == 0) 5327961SNatalie.Li@Sun.COM return (state_map[i].scm_state); 5337961SNatalie.Li@Sun.COM } 5347961SNatalie.Li@Sun.COM 5357961SNatalie.Li@Sun.COM if (strrchr(state, '*') != 0) /* State Transitioning */ 5367961SNatalie.Li@Sun.COM return (SERVICE_STOP_PENDING); 5377961SNatalie.Li@Sun.COM 5387961SNatalie.Li@Sun.COM return (SERVICE_RUNNING); 5397961SNatalie.Li@Sun.COM } 5407961SNatalie.Li@Sun.COM 5417961SNatalie.Li@Sun.COM /* 5427961SNatalie.Li@Sun.COM * svcctl_scm_enum_services 5437961SNatalie.Li@Sun.COM * 54410001SJoyce.McIntosh@Sun.COM * Enumerates SMF services: handles wide-char or ascii requests. 54510001SJoyce.McIntosh@Sun.COM * 54610001SJoyce.McIntosh@Sun.COM * Returns the number of services written to buf. 5477961SNatalie.Li@Sun.COM */ 54810001SJoyce.McIntosh@Sun.COM uint32_t 54910001SJoyce.McIntosh@Sun.COM svcctl_scm_enum_services(svcctl_manager_context_t *mgr_ctx, uint8_t *buf, 55010001SJoyce.McIntosh@Sun.COM size_t buflen, uint32_t *resume_handle, boolean_t use_wchar) 5517961SNatalie.Li@Sun.COM { 55210001SJoyce.McIntosh@Sun.COM svcctl_svc_node_t *node; 55310001SJoyce.McIntosh@Sun.COM int base_offset, offset; 55410001SJoyce.McIntosh@Sun.COM mts_wchar_t *w_name; 55510001SJoyce.McIntosh@Sun.COM char *a_name; 55610001SJoyce.McIntosh@Sun.COM char *node_name; 55710001SJoyce.McIntosh@Sun.COM size_t namelen; 55810001SJoyce.McIntosh@Sun.COM uint32_t numsvcs = mgr_ctx->mc_scf_numsvcs; 55910001SJoyce.McIntosh@Sun.COM uint32_t ns; 56010001SJoyce.McIntosh@Sun.COM /*LINTED E_BAD_PTR_CAST_ALIGN*/ 56110001SJoyce.McIntosh@Sun.COM svc_enum_status_t *svc = (svc_enum_status_t *)buf; 5627961SNatalie.Li@Sun.COM 56310001SJoyce.McIntosh@Sun.COM if (buf == NULL || buflen == 0 || *resume_handle >= numsvcs) { 56410001SJoyce.McIntosh@Sun.COM *resume_handle = 0; 56510001SJoyce.McIntosh@Sun.COM return (0); 56610001SJoyce.McIntosh@Sun.COM } 5677961SNatalie.Li@Sun.COM 56810001SJoyce.McIntosh@Sun.COM base_offset = numsvcs * sizeof (svc_enum_status_t); 56910001SJoyce.McIntosh@Sun.COM if (buflen < mgr_ctx->mc_bytes_needed) { 57010001SJoyce.McIntosh@Sun.COM while (base_offset > (buflen / 4)) { 57110001SJoyce.McIntosh@Sun.COM --numsvcs; 57210001SJoyce.McIntosh@Sun.COM base_offset = numsvcs * sizeof (svc_enum_status_t); 57310001SJoyce.McIntosh@Sun.COM } 57410001SJoyce.McIntosh@Sun.COM } 5757961SNatalie.Li@Sun.COM 5767961SNatalie.Li@Sun.COM offset = base_offset; 5777961SNatalie.Li@Sun.COM node = uu_avl_first(mgr_ctx->mc_svcs); 5787961SNatalie.Li@Sun.COM 57910001SJoyce.McIntosh@Sun.COM for (ns = 0; ((ns < *resume_handle) && (node != NULL)); ++ns) 58010001SJoyce.McIntosh@Sun.COM node = uu_avl_next(mgr_ctx->mc_svcs, node); 58110001SJoyce.McIntosh@Sun.COM 58210001SJoyce.McIntosh@Sun.COM if (node == NULL) { 58310001SJoyce.McIntosh@Sun.COM *resume_handle = 0; 58410001SJoyce.McIntosh@Sun.COM return (0); 58510001SJoyce.McIntosh@Sun.COM } 58610001SJoyce.McIntosh@Sun.COM 58710001SJoyce.McIntosh@Sun.COM for (ns = 0; ((ns < numsvcs) && (node != NULL)); ++ns) { 58810001SJoyce.McIntosh@Sun.COM node_name = node->sn_name; 58910001SJoyce.McIntosh@Sun.COM namelen = strlen(node_name) + 1; 59010001SJoyce.McIntosh@Sun.COM svc[ns].svc_name = offset; 5917961SNatalie.Li@Sun.COM 59210001SJoyce.McIntosh@Sun.COM if (use_wchar) { 59310001SJoyce.McIntosh@Sun.COM /*LINTED E_BAD_PTR_CAST_ALIGN*/ 59410001SJoyce.McIntosh@Sun.COM w_name = (mts_wchar_t *)&buf[offset]; 59510001SJoyce.McIntosh@Sun.COM (void) mts_mbstowcs(w_name, node_name, namelen); 59610001SJoyce.McIntosh@Sun.COM offset += SVCCTL_WNSTRLEN(node_name); 59710001SJoyce.McIntosh@Sun.COM } else { 59810001SJoyce.McIntosh@Sun.COM a_name = (char *)&buf[offset]; 59910001SJoyce.McIntosh@Sun.COM (void) strlcpy(a_name, node_name, namelen); 60010001SJoyce.McIntosh@Sun.COM offset += namelen; 60110001SJoyce.McIntosh@Sun.COM } 60210001SJoyce.McIntosh@Sun.COM 60310001SJoyce.McIntosh@Sun.COM if (offset >= buflen) 60410001SJoyce.McIntosh@Sun.COM break; 6057961SNatalie.Li@Sun.COM 60610001SJoyce.McIntosh@Sun.COM node_name = node->sn_fmri; 60710001SJoyce.McIntosh@Sun.COM namelen = strlen(node_name) + 1; 60810001SJoyce.McIntosh@Sun.COM svc[ns].display_name = offset; 6097961SNatalie.Li@Sun.COM 61010001SJoyce.McIntosh@Sun.COM if (use_wchar) { 61110001SJoyce.McIntosh@Sun.COM /*LINTED E_BAD_PTR_CAST_ALIGN*/ 61210001SJoyce.McIntosh@Sun.COM w_name = (mts_wchar_t *)&buf[offset]; 61310001SJoyce.McIntosh@Sun.COM (void) mts_mbstowcs(w_name, node_name, namelen); 61410001SJoyce.McIntosh@Sun.COM offset += SVCCTL_WNSTRLEN(node_name); 61510001SJoyce.McIntosh@Sun.COM } else { 61610001SJoyce.McIntosh@Sun.COM a_name = (char *)&buf[offset]; 61710001SJoyce.McIntosh@Sun.COM (void) strlcpy(a_name, node_name, namelen); 61810001SJoyce.McIntosh@Sun.COM offset += namelen; 61910001SJoyce.McIntosh@Sun.COM } 62010001SJoyce.McIntosh@Sun.COM 62110001SJoyce.McIntosh@Sun.COM if (offset >= buflen) 62210001SJoyce.McIntosh@Sun.COM break; 62310001SJoyce.McIntosh@Sun.COM 62410001SJoyce.McIntosh@Sun.COM svc[ns].svc_status.cur_state = 6257961SNatalie.Li@Sun.COM svcctl_scm_map_status(node->sn_state); 62610001SJoyce.McIntosh@Sun.COM svc[ns].svc_status.service_type = SERVICE_WIN32_SHARE_PROCESS; 62710001SJoyce.McIntosh@Sun.COM svc[ns].svc_status.ctrl_accepted = 0; 62810001SJoyce.McIntosh@Sun.COM svc[ns].svc_status.w32_exitcode = 0; 62910001SJoyce.McIntosh@Sun.COM svc[ns].svc_status.svc_specified_exitcode = 0; 63010001SJoyce.McIntosh@Sun.COM svc[ns].svc_status.check_point = 0; 63110001SJoyce.McIntosh@Sun.COM svc[ns].svc_status.wait_hint = 0; 6327961SNatalie.Li@Sun.COM 6337961SNatalie.Li@Sun.COM node = uu_avl_next(mgr_ctx->mc_svcs, node); 6347961SNatalie.Li@Sun.COM } 63510001SJoyce.McIntosh@Sun.COM 63610001SJoyce.McIntosh@Sun.COM if (node == NULL) { 63710001SJoyce.McIntosh@Sun.COM *resume_handle = 0; 63810001SJoyce.McIntosh@Sun.COM } else { 63910001SJoyce.McIntosh@Sun.COM *resume_handle += ns; 64010001SJoyce.McIntosh@Sun.COM 64110001SJoyce.McIntosh@Sun.COM if (*resume_handle >= mgr_ctx->mc_scf_numsvcs) 64210001SJoyce.McIntosh@Sun.COM *resume_handle = 0; 64310001SJoyce.McIntosh@Sun.COM } 64410001SJoyce.McIntosh@Sun.COM 64510001SJoyce.McIntosh@Sun.COM return (ns); 6467961SNatalie.Li@Sun.COM } 6477961SNatalie.Li@Sun.COM 6487961SNatalie.Li@Sun.COM /* 6497961SNatalie.Li@Sun.COM * svcctl_scm_cb_bytes_needed 6507961SNatalie.Li@Sun.COM * 6517961SNatalie.Li@Sun.COM * Callback function to calculate bytes needed to enumerate SMF services. 6527961SNatalie.Li@Sun.COM */ 6537961SNatalie.Li@Sun.COM static int 6547961SNatalie.Li@Sun.COM svcctl_scm_cb_bytes_needed(void *svc_node, void *byte_cnt) 6557961SNatalie.Li@Sun.COM { 6567961SNatalie.Li@Sun.COM svcctl_svc_node_t *node = svc_node; 6577961SNatalie.Li@Sun.COM int *cnt = byte_cnt; 6587961SNatalie.Li@Sun.COM 6597961SNatalie.Li@Sun.COM *cnt += (strlen(node->sn_fmri) + 1) * sizeof (mts_wchar_t); 6607961SNatalie.Li@Sun.COM *cnt += (strlen(node->sn_name) + 1) * sizeof (mts_wchar_t); 6617961SNatalie.Li@Sun.COM 6627961SNatalie.Li@Sun.COM return (UU_WALK_NEXT); 6637961SNatalie.Li@Sun.COM } 6647961SNatalie.Li@Sun.COM 6657961SNatalie.Li@Sun.COM /* 6667961SNatalie.Li@Sun.COM * svcctl_scm_bytes_needed 6677961SNatalie.Li@Sun.COM * 6687961SNatalie.Li@Sun.COM * Calculates bytes needed to enumerate SMF services. 6697961SNatalie.Li@Sun.COM */ 670*10122SJordan.Brown@Sun.COM static void 6717961SNatalie.Li@Sun.COM svcctl_scm_bytes_needed(svcctl_manager_context_t *mgr_ctx) 6727961SNatalie.Li@Sun.COM { 6737961SNatalie.Li@Sun.COM int bytes_needed = 0, svc_enum_status_size = 0; 6747961SNatalie.Li@Sun.COM 6757961SNatalie.Li@Sun.COM (void) uu_avl_walk(mgr_ctx->mc_svcs, svcctl_scm_cb_bytes_needed, 6767961SNatalie.Li@Sun.COM &bytes_needed, 0); 6777961SNatalie.Li@Sun.COM 6787961SNatalie.Li@Sun.COM svc_enum_status_size = 6797961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_numsvcs * sizeof (svc_enum_status_t); 6807961SNatalie.Li@Sun.COM bytes_needed += svc_enum_status_size; 6817961SNatalie.Li@Sun.COM 6827961SNatalie.Li@Sun.COM mgr_ctx->mc_bytes_needed = bytes_needed; 6837961SNatalie.Li@Sun.COM } 6847961SNatalie.Li@Sun.COM 6857961SNatalie.Li@Sun.COM /* 6867961SNatalie.Li@Sun.COM * svcctl_scm_validate_service 6877961SNatalie.Li@Sun.COM * 6887961SNatalie.Li@Sun.COM * Check to see whether or not a service is supported. 6897961SNatalie.Li@Sun.COM * 6907961SNatalie.Li@Sun.COM * Returns: 6917961SNatalie.Li@Sun.COM * ERROR_SUCCESS 6927961SNatalie.Li@Sun.COM * ERROR_SERVICE_DOES_NOT_EXIST 6937961SNatalie.Li@Sun.COM */ 6947961SNatalie.Li@Sun.COM uint32_t 6957961SNatalie.Li@Sun.COM svcctl_scm_validate_service(svcctl_manager_context_t *mgr_ctx, char *svc_name) 6967961SNatalie.Li@Sun.COM { 6978474SJose.Borrego@Sun.COM if (svcctl_scm_find_service(mgr_ctx, svc_name) != NULL) 6987961SNatalie.Li@Sun.COM return (ERROR_SUCCESS); 6997961SNatalie.Li@Sun.COM 7007961SNatalie.Li@Sun.COM return (ERROR_SERVICE_DOES_NOT_EXIST); 7017961SNatalie.Li@Sun.COM } 7027961SNatalie.Li@Sun.COM 7037961SNatalie.Li@Sun.COM /* 7048474SJose.Borrego@Sun.COM * svcctl_scm_map_windows_svc 7058474SJose.Borrego@Sun.COM * 7068474SJose.Borrego@Sun.COM * Windows client send windows service name. This method maps windows 7078474SJose.Borrego@Sun.COM * service names to Solaris service names. 7088474SJose.Borrego@Sun.COM */ 7098474SJose.Borrego@Sun.COM static char * 7108474SJose.Borrego@Sun.COM svcctl_scm_map_windows_svc(char *svc_name) 7118474SJose.Borrego@Sun.COM { 7128474SJose.Borrego@Sun.COM int i, size = 0; 7138474SJose.Borrego@Sun.COM struct { 7148474SJose.Borrego@Sun.COM char *win_svc_name; 7158474SJose.Borrego@Sun.COM char *solaris_svc_name; 7168474SJose.Borrego@Sun.COM } win2solaris_svc_map[] = { 71710001SJoyce.McIntosh@Sun.COM { "eventlog", "system/system-log:default" }, 71810001SJoyce.McIntosh@Sun.COM { "RemoteRegistry", "system/svc/restarter:default" }, 71910001SJoyce.McIntosh@Sun.COM { "spooler", "application/print/ppd-cache-update:default" } 7208474SJose.Borrego@Sun.COM }; 7218474SJose.Borrego@Sun.COM 7228474SJose.Borrego@Sun.COM size = sizeof (win2solaris_svc_map)/sizeof (win2solaris_svc_map[0]); 7238474SJose.Borrego@Sun.COM for (i = 0; i < size; ++i) { 7248474SJose.Borrego@Sun.COM if (strcasecmp(svc_name, 7258474SJose.Borrego@Sun.COM win2solaris_svc_map[i].win_svc_name) == 0) 7268474SJose.Borrego@Sun.COM return (win2solaris_svc_map[i].solaris_svc_name); 7278474SJose.Borrego@Sun.COM } 7288474SJose.Borrego@Sun.COM 7298474SJose.Borrego@Sun.COM return (NULL); 7308474SJose.Borrego@Sun.COM } 7318474SJose.Borrego@Sun.COM 7328474SJose.Borrego@Sun.COM /* 7337961SNatalie.Li@Sun.COM * svcctl_scm_find_service 7347961SNatalie.Li@Sun.COM * 7357961SNatalie.Li@Sun.COM * Lookup a service. 7367961SNatalie.Li@Sun.COM */ 7377961SNatalie.Li@Sun.COM svcctl_svc_node_t * 7387961SNatalie.Li@Sun.COM svcctl_scm_find_service(svcctl_manager_context_t *mgr_ctx, char *svc_name) 7397961SNatalie.Li@Sun.COM { 7407961SNatalie.Li@Sun.COM svcctl_svc_node_t node; 7417961SNatalie.Li@Sun.COM uu_avl_index_t idx; 7427961SNatalie.Li@Sun.COM svcctl_svc_node_t *f_node = NULL; 7437961SNatalie.Li@Sun.COM 7447961SNatalie.Li@Sun.COM if (svc_name == NULL) 7457961SNatalie.Li@Sun.COM return (NULL); 7467961SNatalie.Li@Sun.COM 7477961SNatalie.Li@Sun.COM bzero(&node, sizeof (svcctl_svc_node_t)); 7487961SNatalie.Li@Sun.COM node.sn_name = svc_name; 7497961SNatalie.Li@Sun.COM f_node = uu_avl_find(mgr_ctx->mc_svcs, &node, 7507961SNatalie.Li@Sun.COM &mgr_ctx->mc_scf_max_fmri_len, &idx); 7517961SNatalie.Li@Sun.COM if (f_node != NULL) 7527961SNatalie.Li@Sun.COM return (f_node); 7537961SNatalie.Li@Sun.COM 7548474SJose.Borrego@Sun.COM bzero(&node, sizeof (svcctl_svc_node_t)); 7558474SJose.Borrego@Sun.COM node.sn_name = svcctl_scm_map_windows_svc(svc_name); 7568474SJose.Borrego@Sun.COM if (node.sn_name != NULL) 7578474SJose.Borrego@Sun.COM f_node = uu_avl_find(mgr_ctx->mc_svcs, &node, 7588474SJose.Borrego@Sun.COM &mgr_ctx->mc_scf_max_fmri_len, &idx); 7598474SJose.Borrego@Sun.COM 7608474SJose.Borrego@Sun.COM return (f_node); 7617961SNatalie.Li@Sun.COM } 7627961SNatalie.Li@Sun.COM 7637961SNatalie.Li@Sun.COM /* 7647961SNatalie.Li@Sun.COM * svcctl_scm_refresh 7657961SNatalie.Li@Sun.COM * 7667961SNatalie.Li@Sun.COM * Refresh SCM services per context. 7677961SNatalie.Li@Sun.COM */ 7687961SNatalie.Li@Sun.COM int 7697961SNatalie.Li@Sun.COM svcctl_scm_refresh(svcctl_manager_context_t *mgr_ctx) 7707961SNatalie.Li@Sun.COM { 7717961SNatalie.Li@Sun.COM svcctl_scm_fini(mgr_ctx); 772*10122SJordan.Brown@Sun.COM 773*10122SJordan.Brown@Sun.COM if (svcctl_scm_ops.svcctl_op_scm_init != NULL) 774*10122SJordan.Brown@Sun.COM return (svcctl_scm_ops.svcctl_op_scm_init(mgr_ctx)); 775*10122SJordan.Brown@Sun.COM 7767961SNatalie.Li@Sun.COM return (svcctl_scm_init(mgr_ctx)); 7777961SNatalie.Li@Sun.COM } 7787961SNatalie.Li@Sun.COM 7797961SNatalie.Li@Sun.COM /* 7807961SNatalie.Li@Sun.COM * svcctl_scm_scf_handle_init 7817961SNatalie.Li@Sun.COM * 7827961SNatalie.Li@Sun.COM * Initialize SCF handle per context. 7837961SNatalie.Li@Sun.COM */ 7847961SNatalie.Li@Sun.COM int 7857961SNatalie.Li@Sun.COM svcctl_scm_scf_handle_init(svcctl_manager_context_t *mgr_ctx) 7867961SNatalie.Li@Sun.COM { 787*10122SJordan.Brown@Sun.COM if (svcctl_scm_ops.svcctl_op_scf_init != NULL) 788*10122SJordan.Brown@Sun.COM return (svcctl_scm_ops. 789*10122SJordan.Brown@Sun.COM svcctl_op_scf_init(mgr_ctx)); 790*10122SJordan.Brown@Sun.COM 7917961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_hdl = scf_handle_create(SCF_VERSION); 7927961SNatalie.Li@Sun.COM if (mgr_ctx->mc_scf_hdl == NULL) 7937961SNatalie.Li@Sun.COM return (-1); 7947961SNatalie.Li@Sun.COM 7957961SNatalie.Li@Sun.COM if (scf_handle_bind(mgr_ctx->mc_scf_hdl) == -1) { 7967961SNatalie.Li@Sun.COM scf_handle_destroy(mgr_ctx->mc_scf_hdl); 7977961SNatalie.Li@Sun.COM return (-1); 7987961SNatalie.Li@Sun.COM } 7997961SNatalie.Li@Sun.COM 8007961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gpg = scf_pg_create(mgr_ctx->mc_scf_hdl); 8017961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gprop = scf_property_create(mgr_ctx->mc_scf_hdl); 8027961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_gval = scf_value_create(mgr_ctx->mc_scf_hdl); 8037961SNatalie.Li@Sun.COM 8047961SNatalie.Li@Sun.COM if ((mgr_ctx->mc_scf_gpg == NULL) || 8057961SNatalie.Li@Sun.COM (mgr_ctx->mc_scf_gprop == NULL) || 8067961SNatalie.Li@Sun.COM (mgr_ctx->mc_scf_gval == NULL)) { 8077961SNatalie.Li@Sun.COM (void) scf_handle_unbind(mgr_ctx->mc_scf_hdl); 8087961SNatalie.Li@Sun.COM scf_handle_destroy(mgr_ctx->mc_scf_hdl); 8097961SNatalie.Li@Sun.COM return (-1); 8107961SNatalie.Li@Sun.COM } 8117961SNatalie.Li@Sun.COM 8127961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 8137961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_max_value_len = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); 8147961SNatalie.Li@Sun.COM 8157961SNatalie.Li@Sun.COM return (0); 8167961SNatalie.Li@Sun.COM } 8177961SNatalie.Li@Sun.COM 8187961SNatalie.Li@Sun.COM /* 8197961SNatalie.Li@Sun.COM * svcctl_scm_scf_handle_init 8207961SNatalie.Li@Sun.COM * 8217961SNatalie.Li@Sun.COM * Destroy SCF handle per context. 8227961SNatalie.Li@Sun.COM */ 8237961SNatalie.Li@Sun.COM void 8247961SNatalie.Li@Sun.COM svcctl_scm_scf_handle_fini(svcctl_manager_context_t *mgr_ctx) 8257961SNatalie.Li@Sun.COM { 8267961SNatalie.Li@Sun.COM scf_value_destroy(mgr_ctx->mc_scf_gval); 8277961SNatalie.Li@Sun.COM scf_property_destroy(mgr_ctx->mc_scf_gprop); 8287961SNatalie.Li@Sun.COM scf_pg_destroy(mgr_ctx->mc_scf_gpg); 829*10122SJordan.Brown@Sun.COM 830*10122SJordan.Brown@Sun.COM if (mgr_ctx->mc_scf_hdl != NULL) { 831*10122SJordan.Brown@Sun.COM (void) scf_handle_unbind(mgr_ctx->mc_scf_hdl); 832*10122SJordan.Brown@Sun.COM scf_handle_destroy(mgr_ctx->mc_scf_hdl); 833*10122SJordan.Brown@Sun.COM } 8347961SNatalie.Li@Sun.COM } 8357961SNatalie.Li@Sun.COM 8367961SNatalie.Li@Sun.COM /* 8377961SNatalie.Li@Sun.COM * svcctl_scm_init 8387961SNatalie.Li@Sun.COM * 8397961SNatalie.Li@Sun.COM * Initialize SCM repository per context. 8407961SNatalie.Li@Sun.COM * SCM repository holds a list of SMF services. 8417961SNatalie.Li@Sun.COM * Each SMF service node contains state, description and FMRI. 8427961SNatalie.Li@Sun.COM */ 8437961SNatalie.Li@Sun.COM int 8447961SNatalie.Li@Sun.COM svcctl_scm_init(svcctl_manager_context_t *mgr_ctx) 8457961SNatalie.Li@Sun.COM { 8467961SNatalie.Li@Sun.COM int exit_status = 0; 8477961SNatalie.Li@Sun.COM 8487961SNatalie.Li@Sun.COM assert(mgr_ctx->mc_svcs_pool == NULL); 8497961SNatalie.Li@Sun.COM assert(mgr_ctx->mc_svcs == NULL); 8507961SNatalie.Li@Sun.COM 851*10122SJordan.Brown@Sun.COM if (svcctl_scm_ops.svcctl_op_scm_init != NULL) 852*10122SJordan.Brown@Sun.COM return (svcctl_scm_ops.svcctl_op_scm_init(mgr_ctx)); 853*10122SJordan.Brown@Sun.COM 8547961SNatalie.Li@Sun.COM mgr_ctx->mc_svcs_pool = uu_avl_pool_create("smf_svcs_pool", 8557961SNatalie.Li@Sun.COM sizeof (svcctl_svc_node_t), offsetof(svcctl_svc_node_t, sn_node), 8567961SNatalie.Li@Sun.COM svcctl_scm_avl_nodecmp, UU_AVL_DEBUG); 8577961SNatalie.Li@Sun.COM 8587961SNatalie.Li@Sun.COM if (mgr_ctx->mc_svcs_pool == NULL) 8597961SNatalie.Li@Sun.COM return (-1); 8607961SNatalie.Li@Sun.COM 8617961SNatalie.Li@Sun.COM mgr_ctx->mc_svcs = uu_avl_create(mgr_ctx->mc_svcs_pool, NULL, 0); 8627961SNatalie.Li@Sun.COM if (mgr_ctx->mc_svcs == NULL) { 8637961SNatalie.Li@Sun.COM uu_avl_pool_destroy(mgr_ctx->mc_svcs_pool); 8647961SNatalie.Li@Sun.COM return (-1); 8657961SNatalie.Li@Sun.COM } 8667961SNatalie.Li@Sun.COM 8677961SNatalie.Li@Sun.COM if (scf_walk_fmri(mgr_ctx->mc_scf_hdl, 0, NULL, 8687961SNatalie.Li@Sun.COM SCF_WALK_MULTIPLE | SCF_WALK_LEGACY, 8697961SNatalie.Li@Sun.COM svcctl_scm_cb_list_svcinst, mgr_ctx, &exit_status, NULL) != 0) { 8707961SNatalie.Li@Sun.COM uu_avl_destroy(mgr_ctx->mc_svcs); 8717961SNatalie.Li@Sun.COM uu_avl_pool_destroy(mgr_ctx->mc_svcs_pool); 8727961SNatalie.Li@Sun.COM return (-1); 8737961SNatalie.Li@Sun.COM } 8747961SNatalie.Li@Sun.COM 8757961SNatalie.Li@Sun.COM mgr_ctx->mc_scf_numsvcs = uu_avl_numnodes(mgr_ctx->mc_svcs); 8767961SNatalie.Li@Sun.COM if (mgr_ctx->mc_scf_numsvcs > 0) 8777961SNatalie.Li@Sun.COM svcctl_scm_bytes_needed(mgr_ctx); 8787961SNatalie.Li@Sun.COM 8797961SNatalie.Li@Sun.COM return (0); 8807961SNatalie.Li@Sun.COM } 8817961SNatalie.Li@Sun.COM 8827961SNatalie.Li@Sun.COM /* 8837961SNatalie.Li@Sun.COM * svcctl_scm_fini 8847961SNatalie.Li@Sun.COM * 8857961SNatalie.Li@Sun.COM * Destroy SCM repository per context. 8867961SNatalie.Li@Sun.COM */ 8877961SNatalie.Li@Sun.COM void 8887961SNatalie.Li@Sun.COM svcctl_scm_fini(svcctl_manager_context_t *mgr_ctx) 8897961SNatalie.Li@Sun.COM { 8907961SNatalie.Li@Sun.COM uu_avl_walk_t *walk; 8917961SNatalie.Li@Sun.COM svcctl_svc_node_t *node; 8927961SNatalie.Li@Sun.COM 8937961SNatalie.Li@Sun.COM if ((mgr_ctx == NULL) || (mgr_ctx->mc_svcs_pool == NULL) || 8947961SNatalie.Li@Sun.COM (mgr_ctx->mc_svcs == NULL)) 8957961SNatalie.Li@Sun.COM return; 8967961SNatalie.Li@Sun.COM 8977961SNatalie.Li@Sun.COM if ((walk = 8987961SNatalie.Li@Sun.COM uu_avl_walk_start(mgr_ctx->mc_svcs, UU_WALK_ROBUST)) == NULL) 8997961SNatalie.Li@Sun.COM return; 9007961SNatalie.Li@Sun.COM 9017961SNatalie.Li@Sun.COM while ((node = uu_avl_walk_next(walk)) != NULL) { 9027961SNatalie.Li@Sun.COM uu_avl_remove(mgr_ctx->mc_svcs, node); 9037961SNatalie.Li@Sun.COM free(node->sn_name); 9047961SNatalie.Li@Sun.COM free(node->sn_fmri); 9057961SNatalie.Li@Sun.COM free(node->sn_desc); 9067961SNatalie.Li@Sun.COM free(node->sn_state); 9077961SNatalie.Li@Sun.COM free(node); 9087961SNatalie.Li@Sun.COM } 9097961SNatalie.Li@Sun.COM uu_avl_walk_end(walk); 9107961SNatalie.Li@Sun.COM uu_avl_destroy(mgr_ctx->mc_svcs); 9117961SNatalie.Li@Sun.COM uu_avl_pool_destroy(mgr_ctx->mc_svcs_pool); 9127961SNatalie.Li@Sun.COM mgr_ctx->mc_svcs_pool = NULL; 9137961SNatalie.Li@Sun.COM mgr_ctx->mc_svcs = NULL; 9147961SNatalie.Li@Sun.COM } 915*10122SJordan.Brown@Sun.COM 916*10122SJordan.Brown@Sun.COM /* 917*10122SJordan.Brown@Sun.COM * svcctl_init 918*10122SJordan.Brown@Sun.COM * 919*10122SJordan.Brown@Sun.COM * Initializes the SVCCTL service. 920*10122SJordan.Brown@Sun.COM * Initializes handle and ops structure to interposed library. 921*10122SJordan.Brown@Sun.COM */ 922*10122SJordan.Brown@Sun.COM void 923*10122SJordan.Brown@Sun.COM svcctl_init(void) 924*10122SJordan.Brown@Sun.COM { 925*10122SJordan.Brown@Sun.COM svcctl_scm_interposer_hdl = smb_dlopen(); 926*10122SJordan.Brown@Sun.COM if (svcctl_scm_interposer_hdl == NULL) 927*10122SJordan.Brown@Sun.COM return; 928*10122SJordan.Brown@Sun.COM 929*10122SJordan.Brown@Sun.COM bzero((void *)&svcctl_scm_ops, 930*10122SJordan.Brown@Sun.COM sizeof (svcctl_scm_ops)); 931*10122SJordan.Brown@Sun.COM 932*10122SJordan.Brown@Sun.COM svcctl_scm_ops.svcctl_op_scm_init = 933*10122SJordan.Brown@Sun.COM (int (*)())dlsym(svcctl_scm_interposer_hdl, "svcctl_scm_init"); 934*10122SJordan.Brown@Sun.COM 935*10122SJordan.Brown@Sun.COM svcctl_scm_ops.svcctl_op_scf_init = 936*10122SJordan.Brown@Sun.COM (int (*)())dlsym(svcctl_scm_interposer_hdl, 937*10122SJordan.Brown@Sun.COM "svcctl_scm_scf_handle_init"); 938*10122SJordan.Brown@Sun.COM 939*10122SJordan.Brown@Sun.COM if (svcctl_scm_ops.svcctl_op_scm_init == NULL || 940*10122SJordan.Brown@Sun.COM svcctl_scm_ops.svcctl_op_scf_init == NULL) 941*10122SJordan.Brown@Sun.COM svcctl_fini(); 942*10122SJordan.Brown@Sun.COM 943*10122SJordan.Brown@Sun.COM } 944*10122SJordan.Brown@Sun.COM 945*10122SJordan.Brown@Sun.COM /* 946*10122SJordan.Brown@Sun.COM * svcctl_fini 947*10122SJordan.Brown@Sun.COM * 948*10122SJordan.Brown@Sun.COM * Finalizes the SVCCTL service. 949*10122SJordan.Brown@Sun.COM * Closes handle to interposed library. 950*10122SJordan.Brown@Sun.COM */ 951*10122SJordan.Brown@Sun.COM void 952*10122SJordan.Brown@Sun.COM svcctl_fini(void) 953*10122SJordan.Brown@Sun.COM { 954*10122SJordan.Brown@Sun.COM smb_dlclose(svcctl_scm_interposer_hdl); 955*10122SJordan.Brown@Sun.COM svcctl_scm_interposer_hdl = NULL; 956*10122SJordan.Brown@Sun.COM bzero((void *)&svcctl_scm_ops, 957*10122SJordan.Brown@Sun.COM sizeof (svcctl_scm_ops)); 958*10122SJordan.Brown@Sun.COM } 959