17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5fff9db26Svp157776 * Common Development and Distribution License (the "License"). 6fff9db26Svp157776 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22870ad75aSSean Wilcox * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Routines used by inetd to read inetd's configuration from the repository, 287c478bd9Sstevel@tonic-gate * to validate it and setup inetd's data structures appropriately based on 297c478bd9Sstevel@tonic-gate * in. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <errno.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <netdb.h> 377c478bd9Sstevel@tonic-gate #include <netinet/in.h> 387c478bd9Sstevel@tonic-gate #include <libintl.h> 397c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h> 407c478bd9Sstevel@tonic-gate #include <signal.h> 417c478bd9Sstevel@tonic-gate #include <wait.h> 427c478bd9Sstevel@tonic-gate #include "inetd_impl.h" 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* method timeout used if one isn't explicitly specified */ 467c478bd9Sstevel@tonic-gate #define DEFAULT_METHOD_TIMEOUT 10 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* supported method properties and their attributes */ 507c478bd9Sstevel@tonic-gate static inetd_prop_t method_props[] = { 51ba1637f8Smh138676 {PR_EXEC_NAME, "", INET_TYPE_STRING, B_FALSE, IVE_UNSET, NULL, B_FALSE}, 52ba1637f8Smh138676 {PR_ARG0_NAME, "", INET_TYPE_STRING, B_TRUE, IVE_UNSET, NULL, B_FALSE}, 53ba1637f8Smh138676 {SCF_PROPERTY_TIMEOUT, "", INET_TYPE_COUNT, B_TRUE, IVE_UNSET, NULL, B_FALSE}, 54ba1637f8Smh138676 {NULL}, 557c478bd9Sstevel@tonic-gate }; 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* enumeration of method properties; used to index into method_props[] */ 587c478bd9Sstevel@tonic-gate typedef enum { 597c478bd9Sstevel@tonic-gate MP_EXEC, 607c478bd9Sstevel@tonic-gate MP_ARG0, 61ba1637f8Smh138676 MP_TIMEOUT 627c478bd9Sstevel@tonic-gate } method_prop_t; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* handle used for repository access in read_prop() */ 667c478bd9Sstevel@tonic-gate static scf_handle_t *rep_handle = NULL; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* pool used to create proto_info_t lists (generic proto info structure) */ 697c478bd9Sstevel@tonic-gate static uu_list_pool_t *proto_info_pool = NULL; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate static void destroy_method_props(inetd_prop_t *); 727c478bd9Sstevel@tonic-gate static int proto_info_compare(const void *, const void *, void *); 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate int 757c478bd9Sstevel@tonic-gate config_init(void) 767c478bd9Sstevel@tonic-gate { 777c478bd9Sstevel@tonic-gate if ((rep_handle = scf_handle_create(SCF_VERSION)) == NULL) { 787c478bd9Sstevel@tonic-gate error_msg("%s: %s", 797c478bd9Sstevel@tonic-gate gettext("Failed to create repository handle"), 807c478bd9Sstevel@tonic-gate scf_strerror(scf_error())); 817c478bd9Sstevel@tonic-gate return (-1); 827c478bd9Sstevel@tonic-gate } else if (make_handle_bound(rep_handle) == -1) { 837c478bd9Sstevel@tonic-gate /* let config_fini clean-up */ 847c478bd9Sstevel@tonic-gate return (-1); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate if ((proto_info_pool = uu_list_pool_create("proto_info_pool", 887c478bd9Sstevel@tonic-gate sizeof (proto_info_t), offsetof(proto_info_t, link), 897c478bd9Sstevel@tonic-gate proto_info_compare, UU_LIST_POOL_DEBUG)) == NULL) { 907c478bd9Sstevel@tonic-gate error_msg(gettext("Failed to create uu list pool: %s"), 917c478bd9Sstevel@tonic-gate uu_strerror(uu_error())); 927c478bd9Sstevel@tonic-gate return (-1); 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate return (0); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate void 997c478bd9Sstevel@tonic-gate config_fini(void) 1007c478bd9Sstevel@tonic-gate { 1017c478bd9Sstevel@tonic-gate if (rep_handle == NULL) 1027c478bd9Sstevel@tonic-gate return; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate if (proto_info_pool != NULL) { 1057c478bd9Sstevel@tonic-gate uu_list_pool_destroy(proto_info_pool); 1067c478bd9Sstevel@tonic-gate proto_info_pool = NULL; 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(rep_handle); 1107c478bd9Sstevel@tonic-gate scf_handle_destroy(rep_handle); 1117c478bd9Sstevel@tonic-gate rep_handle = NULL; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static void 1157c478bd9Sstevel@tonic-gate destroy_method_info(method_info_t *mi) 1167c478bd9Sstevel@tonic-gate { 1177c478bd9Sstevel@tonic-gate if (mi == NULL) 1187c478bd9Sstevel@tonic-gate return; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate if (mi->wordexp_arg0_backup != NULL) { 1217c478bd9Sstevel@tonic-gate /* 1227c478bd9Sstevel@tonic-gate * Return the wordexp structure back to its original 1237c478bd9Sstevel@tonic-gate * state so it can be consumed by wordfree. 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate free(mi->exec_args_we.we_wordv[0]); 1267c478bd9Sstevel@tonic-gate mi->exec_args_we.we_wordv[0] = 1277c478bd9Sstevel@tonic-gate (char *)mi->wordexp_arg0_backup; 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate free(mi->exec_path); 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate wordfree(&mi->exec_args_we); 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate free(mi); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * Transforms the properties read from the repository for a method into a 1397c478bd9Sstevel@tonic-gate * method_info_t and returns a pointer to it. If expansion of the exec 1407c478bd9Sstevel@tonic-gate * property fails, due to an invalid string or memory allocation failure, 1417c478bd9Sstevel@tonic-gate * NULL is returned and exec_invalid is set appropriately to indicate whether 1427c478bd9Sstevel@tonic-gate * it was a memory allocation failure or an invalid exec string. 1437c478bd9Sstevel@tonic-gate */ 1447c478bd9Sstevel@tonic-gate static method_info_t * 1457c478bd9Sstevel@tonic-gate create_method_info(const inetd_prop_t *mprops, boolean_t *exec_invalid) 1467c478bd9Sstevel@tonic-gate { 1477c478bd9Sstevel@tonic-gate method_info_t *ret; 1487c478bd9Sstevel@tonic-gate int i; 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate if ((ret = calloc(1, sizeof (method_info_t))) == NULL) 1517c478bd9Sstevel@tonic-gate goto alloc_fail; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* Expand the exec string. */ 154ba1637f8Smh138676 if ((i = wordexp(get_prop_value_string(mprops, PR_EXEC_NAME), 1557c478bd9Sstevel@tonic-gate &ret->exec_args_we, WRDE_NOCMD|WRDE_UNDEF)) != 0) { 1567c478bd9Sstevel@tonic-gate if (i == WRDE_NOSPACE) 1577c478bd9Sstevel@tonic-gate goto alloc_fail; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate *exec_invalid = B_TRUE; 1607c478bd9Sstevel@tonic-gate free(ret); 1617c478bd9Sstevel@tonic-gate return (NULL); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate if ((ret->exec_path = strdup(ret->exec_args_we.we_wordv[0])) == NULL) 1657c478bd9Sstevel@tonic-gate goto alloc_fail; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate if (mprops[MP_ARG0].ip_error == IVE_VALID) { /* arg0 is set */ 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * Keep a copy of arg0 of the wordexp structure so that 1707c478bd9Sstevel@tonic-gate * wordfree() gets passed what wordexp() originally returned, 1717c478bd9Sstevel@tonic-gate * as documented as required in the man page. 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate ret->wordexp_arg0_backup = ret->exec_args_we.we_wordv[0]; 1747c478bd9Sstevel@tonic-gate if ((ret->exec_args_we.we_wordv[0] = 175ba1637f8Smh138676 strdup(get_prop_value_string(mprops, PR_ARG0_NAME))) 176ba1637f8Smh138676 == NULL) 1777c478bd9Sstevel@tonic-gate goto alloc_fail; 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate if (mprops[MP_TIMEOUT].ip_error == IVE_VALID) { 181ba1637f8Smh138676 ret->timeout = get_prop_value_count(mprops, 182ba1637f8Smh138676 SCF_PROPERTY_TIMEOUT); 1837c478bd9Sstevel@tonic-gate } else { 1847c478bd9Sstevel@tonic-gate ret->timeout = DEFAULT_METHOD_TIMEOUT; 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate /* exec_invalid not set on success */ 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate return (ret); 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate alloc_fail: 1927c478bd9Sstevel@tonic-gate error_msg(strerror(errno)); 1937c478bd9Sstevel@tonic-gate destroy_method_info(ret); 1947c478bd9Sstevel@tonic-gate *exec_invalid = B_FALSE; 1957c478bd9Sstevel@tonic-gate return (NULL); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* 1997c478bd9Sstevel@tonic-gate * Returns B_TRUE if the contents of the 2 method_info_t structures are 2007c478bd9Sstevel@tonic-gate * equivalent, else B_FALSE. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate boolean_t 2037c478bd9Sstevel@tonic-gate method_info_equal(const method_info_t *mi, const method_info_t *mi2) 2047c478bd9Sstevel@tonic-gate { 2057c478bd9Sstevel@tonic-gate int i; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if ((mi == NULL) && (mi2 == NULL)) { 2087c478bd9Sstevel@tonic-gate return (B_TRUE); 2097c478bd9Sstevel@tonic-gate } else if (((mi == NULL) || (mi2 == NULL)) || 2107c478bd9Sstevel@tonic-gate (mi->exec_args_we.we_wordc != mi2->exec_args_we.we_wordc) || 2117c478bd9Sstevel@tonic-gate (strcmp(mi->exec_path, mi2->exec_path) != 0)) { 2127c478bd9Sstevel@tonic-gate return (B_FALSE); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate for (i = 0; i < mi->exec_args_we.we_wordc; i++) { 2167c478bd9Sstevel@tonic-gate if (strcmp(mi->exec_args_we.we_wordv[i], 2177c478bd9Sstevel@tonic-gate mi2->exec_args_we.we_wordv[i]) != 0) { 2187c478bd9Sstevel@tonic-gate return (B_FALSE); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate return (B_TRUE); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * Checks if the contents of the 2 socket_info_t structures are equivalent. 2277c478bd9Sstevel@tonic-gate * If 'isrpc' is false, the address components of the two structures are 2287c478bd9Sstevel@tonic-gate * compared for equality as part of this. If the two structures are 2297c478bd9Sstevel@tonic-gate * equivalent B_TRUE is returned, else B_FALSE. 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate boolean_t 2327c478bd9Sstevel@tonic-gate socket_info_equal(const socket_info_t *si, const socket_info_t *si2, 2337c478bd9Sstevel@tonic-gate boolean_t isrpc) 2347c478bd9Sstevel@tonic-gate { 2357c478bd9Sstevel@tonic-gate return ((isrpc || (memcmp(&si->local_addr, &si2->local_addr, 2367c478bd9Sstevel@tonic-gate sizeof (si->local_addr)) == 0)) && 2377c478bd9Sstevel@tonic-gate (si->type == si2->type)); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * proto_info_t comparison function. Returns 0 on match, else -1, as required 2437c478bd9Sstevel@tonic-gate * by uu_list_find(). 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate static int 2467c478bd9Sstevel@tonic-gate proto_info_compare(const void *lv, const void *rv, void *istlx) 2477c478bd9Sstevel@tonic-gate { 2487c478bd9Sstevel@tonic-gate proto_info_t *pi = (proto_info_t *)lv; 2497c478bd9Sstevel@tonic-gate proto_info_t *pi2 = (proto_info_t *)rv; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate /* check their RPC configuration matches */ 2527c478bd9Sstevel@tonic-gate if (pi->ri != NULL) { 2537c478bd9Sstevel@tonic-gate if ((pi2->ri == NULL) || !rpc_info_equal(pi->ri, pi2->ri)) 2547c478bd9Sstevel@tonic-gate return (-1); 2557c478bd9Sstevel@tonic-gate } else if (pi2->ri != NULL) { 2567c478bd9Sstevel@tonic-gate return (-1); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate if (pi->v6only != pi2->v6only) 2607c478bd9Sstevel@tonic-gate return (-1); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate if (*(boolean_t *)istlx) { 2637c478bd9Sstevel@tonic-gate if (tlx_info_equal((tlx_info_t *)lv, (tlx_info_t *)rv, 2647c478bd9Sstevel@tonic-gate pi->ri != NULL)) 2657c478bd9Sstevel@tonic-gate return (0); 2667c478bd9Sstevel@tonic-gate } else { 2677c478bd9Sstevel@tonic-gate if (socket_info_equal((socket_info_t *)lv, 2687c478bd9Sstevel@tonic-gate (socket_info_t *)rv, pi->ri != NULL)) 2697c478bd9Sstevel@tonic-gate return (0); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate return (-1); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * Returns B_TRUE if the bind configuration of the two instance_cfg_t 2767c478bd9Sstevel@tonic-gate * structures are equivalent, else B_FALSE. 2777c478bd9Sstevel@tonic-gate */ 2787c478bd9Sstevel@tonic-gate boolean_t 2797c478bd9Sstevel@tonic-gate bind_config_equal(const basic_cfg_t *c1, const basic_cfg_t *c2) 2807c478bd9Sstevel@tonic-gate { 2817c478bd9Sstevel@tonic-gate proto_info_t *pi; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate if ((c1->iswait != c2->iswait) || 2847c478bd9Sstevel@tonic-gate (c1->istlx != c2->istlx)) 2857c478bd9Sstevel@tonic-gate return (B_FALSE); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate if (uu_list_numnodes(c1->proto_list) != 2887c478bd9Sstevel@tonic-gate uu_list_numnodes(c2->proto_list)) 2897c478bd9Sstevel@tonic-gate return (B_FALSE); 2907c478bd9Sstevel@tonic-gate /* 2917c478bd9Sstevel@tonic-gate * For each element in the first configuration's socket/tlx list, 2927c478bd9Sstevel@tonic-gate * check there's a matching one in the other list. 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate for (pi = uu_list_first(c1->proto_list); pi != NULL; 2957c478bd9Sstevel@tonic-gate pi = uu_list_next(c1->proto_list, pi)) { 2967c478bd9Sstevel@tonic-gate uu_list_index_t idx; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if (uu_list_find(c2->proto_list, pi, (void *)&c1->istlx, 2997c478bd9Sstevel@tonic-gate &idx) == NULL) 3007c478bd9Sstevel@tonic-gate return (B_FALSE); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate return (B_TRUE); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* 3077c478bd9Sstevel@tonic-gate * Write the default values contained in 'bprops', read by 3087c478bd9Sstevel@tonic-gate * read_instance_props(), into 'cfg'. 3097c478bd9Sstevel@tonic-gate * Returns -1 if memory allocation fails, else 0. 3107c478bd9Sstevel@tonic-gate */ 3117c478bd9Sstevel@tonic-gate static int 3127c478bd9Sstevel@tonic-gate populate_defaults(inetd_prop_t *bprops, basic_cfg_t *cfg) 3137c478bd9Sstevel@tonic-gate { 314ba1637f8Smh138676 cfg->do_tcp_wrappers = get_prop_value_boolean(bprops, 315ba1637f8Smh138676 PR_DO_TCP_WRAPPERS_NAME); 316ba1637f8Smh138676 cfg->do_tcp_trace = get_prop_value_boolean(bprops, 317ba1637f8Smh138676 PR_DO_TCP_TRACE_NAME); 318*e23de8e2SGary Mills cfg->do_tcp_keepalive = get_prop_value_boolean(bprops, 319*e23de8e2SGary Mills PR_DO_TCP_KEEPALIVE_NAME); 320ba1637f8Smh138676 cfg->inherit_env = get_prop_value_boolean(bprops, PR_INHERIT_ENV_NAME); 321ba1637f8Smh138676 cfg->wait_fail_cnt = get_prop_value_int(bprops, 322ba1637f8Smh138676 PR_MAX_FAIL_RATE_CNT_NAME); 323ba1637f8Smh138676 cfg->wait_fail_interval = get_prop_value_int(bprops, 3247c478bd9Sstevel@tonic-gate PR_MAX_FAIL_RATE_INTVL_NAME); 325ba1637f8Smh138676 cfg->max_copies = get_prop_value_int(bprops, PR_MAX_COPIES_NAME); 326ba1637f8Smh138676 cfg->conn_rate_offline = get_prop_value_int(bprops, 327ba1637f8Smh138676 PR_CON_RATE_OFFLINE_NAME); 328ba1637f8Smh138676 cfg->conn_rate_max = get_prop_value_int(bprops, PR_CON_RATE_MAX_NAME); 329ba1637f8Smh138676 cfg->bind_fail_interval = get_prop_value_int(bprops, 330ba1637f8Smh138676 PR_BIND_FAIL_INTVL_NAME); 331ba1637f8Smh138676 cfg->bind_fail_max = get_prop_value_int(bprops, PR_BIND_FAIL_MAX_NAME); 332fff9db26Svp157776 cfg->conn_backlog = get_prop_value_int(bprops, 333fff9db26Svp157776 PR_CONNECTION_BACKLOG_NAME); 3347c478bd9Sstevel@tonic-gate if ((cfg->bind_addr = 335ba1637f8Smh138676 strdup(get_prop_value_string(bprops, PR_BIND_ADDR_NAME))) == NULL) { 3367c478bd9Sstevel@tonic-gate error_msg(strerror(errno)); 3377c478bd9Sstevel@tonic-gate return (-1); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate return (0); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate void 3437c478bd9Sstevel@tonic-gate destroy_method_infos(method_info_t **mis) 3447c478bd9Sstevel@tonic-gate { 3457c478bd9Sstevel@tonic-gate int i; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate for (i = 0; i < NUM_METHODS; i++) { 3487c478bd9Sstevel@tonic-gate destroy_method_info(mis[i]); 3497c478bd9Sstevel@tonic-gate mis[i] = NULL; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate /* 3547c478bd9Sstevel@tonic-gate * For each method, if it was specifed convert its entry in 'mprops', 3557c478bd9Sstevel@tonic-gate * into an entry in 'mis'. Returns -1 if memory allocation fails or one of the 3567c478bd9Sstevel@tonic-gate * exec strings was invalid, else 0. 3577c478bd9Sstevel@tonic-gate */ 3587c478bd9Sstevel@tonic-gate static int 3597c478bd9Sstevel@tonic-gate create_method_infos(const char *fmri, inetd_prop_t **mprops, 3607c478bd9Sstevel@tonic-gate method_info_t **mis) 3617c478bd9Sstevel@tonic-gate { 3627c478bd9Sstevel@tonic-gate int i; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate for (i = 0; i < NUM_METHODS; i++) { 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * Only create a method info structure if the method properties 3677c478bd9Sstevel@tonic-gate * contain an exec string, which we take to mean the method 3687c478bd9Sstevel@tonic-gate * is specified. 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate if (mprops[i][MP_EXEC].ip_error == IVE_VALID) { 3717c478bd9Sstevel@tonic-gate boolean_t exec_invalid; 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate if ((mis[i] = create_method_info(mprops[i], 3747c478bd9Sstevel@tonic-gate &exec_invalid)) == NULL) { 3757c478bd9Sstevel@tonic-gate if (exec_invalid) { 3767c478bd9Sstevel@tonic-gate error_msg(gettext("Property %s for " 3777c478bd9Sstevel@tonic-gate "method %s of instance %s is " 3787c478bd9Sstevel@tonic-gate "invalid"), PR_EXEC_NAME, 3797c478bd9Sstevel@tonic-gate methods[i].name, fmri); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate return (-1); 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate return (0); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* 3897c478bd9Sstevel@tonic-gate * Try and read each of the method properties for the method 'method' of 3907c478bd9Sstevel@tonic-gate * instance 'inst', and return a table containing all method properties. If an 3917c478bd9Sstevel@tonic-gate * error occurs, NULL is returned, with 'err' set to indicate the cause. 3927c478bd9Sstevel@tonic-gate * Otherwise, a pointer to an inetd_prop_t table is returned containing all 3937c478bd9Sstevel@tonic-gate * the method properties, and each of the properties is flagged according to 3947c478bd9Sstevel@tonic-gate * whether it was present or not, and if it was present its value is set in 3957c478bd9Sstevel@tonic-gate * the property's entry in the table. 3967c478bd9Sstevel@tonic-gate */ 3977c478bd9Sstevel@tonic-gate static inetd_prop_t * 3987c478bd9Sstevel@tonic-gate read_method_props(const char *inst, instance_method_t method, scf_error_t *err) 3997c478bd9Sstevel@tonic-gate { 4007c478bd9Sstevel@tonic-gate inetd_prop_t *ret; 4017c478bd9Sstevel@tonic-gate int i; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate if ((ret = calloc(1, sizeof (method_props))) == NULL) { 4047c478bd9Sstevel@tonic-gate *err = SCF_ERROR_NO_MEMORY; 4057c478bd9Sstevel@tonic-gate return (NULL); 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate (void) memcpy(ret, method_props, sizeof (method_props)); 409ba1637f8Smh138676 for (i = 0; ret[i].ip_name != NULL; i++) { 4107c478bd9Sstevel@tonic-gate *err = read_prop(rep_handle, &ret[i], i, inst, 4117c478bd9Sstevel@tonic-gate methods[method].name); 4127c478bd9Sstevel@tonic-gate if ((*err != 0) && (*err != SCF_ERROR_NOT_FOUND)) { 4137c478bd9Sstevel@tonic-gate destroy_method_props(ret); 4147c478bd9Sstevel@tonic-gate return (NULL); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate return (ret); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate static void 4227c478bd9Sstevel@tonic-gate destroy_method_props(inetd_prop_t *mprop) 4237c478bd9Sstevel@tonic-gate { 4247c478bd9Sstevel@tonic-gate int i; 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate if (mprop == NULL) 4277c478bd9Sstevel@tonic-gate return; 4287c478bd9Sstevel@tonic-gate 429ba1637f8Smh138676 for (i = 0; mprop[i].ip_name != NULL; i++) { 430ba1637f8Smh138676 if (mprop[i].ip_type == INET_TYPE_STRING && 431ba1637f8Smh138676 mprop[i].ip_error == IVE_VALID) 432ba1637f8Smh138676 free(mprop[i].ip_value.iv_string); 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate free(mprop); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * Destroy the basic and method properties returned by read_inst_props(). 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate static void 4427c478bd9Sstevel@tonic-gate destroy_inst_props(inetd_prop_t *bprops, inetd_prop_t **mprops) 4437c478bd9Sstevel@tonic-gate { 4447c478bd9Sstevel@tonic-gate int i; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate free_instance_props(bprops); 4477c478bd9Sstevel@tonic-gate for (i = 0; i < NUM_METHODS; i++) 4487c478bd9Sstevel@tonic-gate destroy_method_props(mprops[i]); 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate /* 4527c478bd9Sstevel@tonic-gate * Read all the basic and method properties for instance 'inst', as inetd_prop_t 4537c478bd9Sstevel@tonic-gate * tables, into the spaces referenced by 'bprops' and 'mprops' respectively. 4547c478bd9Sstevel@tonic-gate * Each of the properties in the tables are flagged to indicate if the 4557c478bd9Sstevel@tonic-gate * property was present or not, and if it was the value is stored within it. 4567c478bd9Sstevel@tonic-gate * If an error occurs at any time -1 is returned and 'err' is set to 4577c478bd9Sstevel@tonic-gate * indicate the reason, else 0 is returned. 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate static int 4607c478bd9Sstevel@tonic-gate read_inst_props(const char *fmri, inetd_prop_t **bprops, 4617c478bd9Sstevel@tonic-gate inetd_prop_t **mprops, scf_error_t *err) 4627c478bd9Sstevel@tonic-gate { 4637c478bd9Sstevel@tonic-gate size_t nprops; 4647c478bd9Sstevel@tonic-gate int i; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if ((*bprops = read_instance_props(rep_handle, (char *)fmri, &nprops, 4677c478bd9Sstevel@tonic-gate err)) == NULL) 4687c478bd9Sstevel@tonic-gate return (-1); 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate for (i = 0; i < NUM_METHODS; i++) { 4717c478bd9Sstevel@tonic-gate if ((mprops[i] = 4727c478bd9Sstevel@tonic-gate read_method_props(fmri, (instance_method_t)i, err)) == 4737c478bd9Sstevel@tonic-gate NULL) { 4747c478bd9Sstevel@tonic-gate for (i--; i >= 0; i--) 4757c478bd9Sstevel@tonic-gate destroy_method_props(mprops[i]); 4767c478bd9Sstevel@tonic-gate free_instance_props(*bprops); 4777c478bd9Sstevel@tonic-gate return (-1); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate return (0); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* 4857c478bd9Sstevel@tonic-gate * Returns B_TRUE if all required properties were read from the repository 4867c478bd9Sstevel@tonic-gate * (whether taken from the defaults or directly from the instance), they 4877c478bd9Sstevel@tonic-gate * all had valid values, all the required methods were present, and they 4887c478bd9Sstevel@tonic-gate * each had the required properties with valid values. Else, returns B_FALSE. 4897c478bd9Sstevel@tonic-gate * If the function returns B_TRUE, the storage referenced by 'cfg' is set 4907c478bd9Sstevel@tonic-gate * to point at an allocated instance_cfg_t initialized based on the basic 4917c478bd9Sstevel@tonic-gate * properties (not method or defaults). 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate static boolean_t 4947c478bd9Sstevel@tonic-gate valid_inst_props(const char *fmri, inetd_prop_t *bprops, inetd_prop_t **mprops, 4957c478bd9Sstevel@tonic-gate basic_cfg_t **cfg) 4967c478bd9Sstevel@tonic-gate { 4977c478bd9Sstevel@tonic-gate boolean_t valid; 4987c478bd9Sstevel@tonic-gate size_t num_bprops; 4997c478bd9Sstevel@tonic-gate int i; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate valid = valid_props(bprops, fmri, cfg, proto_info_pool, conn_ind_pool); 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate /* 5047c478bd9Sstevel@tonic-gate * Double check we've got all necessary properties (valid_props() 5057c478bd9Sstevel@tonic-gate * doesn't enforce the presence of defaults), and output error messages 5067c478bd9Sstevel@tonic-gate * for each invalid/ missing property. 5077c478bd9Sstevel@tonic-gate */ 5087c478bd9Sstevel@tonic-gate (void) get_prop_table(&num_bprops); 509ba1637f8Smh138676 for (i = 0; bprops[i].ip_name != NULL; i++) { 5107c478bd9Sstevel@tonic-gate switch (bprops[i].ip_error) { 5117c478bd9Sstevel@tonic-gate case IVE_UNSET: 5127c478bd9Sstevel@tonic-gate if (!bprops[i].ip_default) 5137c478bd9Sstevel@tonic-gate continue; 5147c478bd9Sstevel@tonic-gate if ((i == PT_ARG0_INDEX) || (i == PT_EXEC_INDEX)) 5157c478bd9Sstevel@tonic-gate continue; 5167c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 5177c478bd9Sstevel@tonic-gate case IVE_INVALID: 5187c478bd9Sstevel@tonic-gate error_msg(gettext("Property '%s' of instance " 5197c478bd9Sstevel@tonic-gate "%s is missing, inconsistent or invalid"), 5207c478bd9Sstevel@tonic-gate bprops[i].ip_name, fmri); 5217c478bd9Sstevel@tonic-gate valid = B_FALSE; 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate for (i = 0; i < NUM_METHODS; i++) { 5267c478bd9Sstevel@tonic-gate int j; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate /* check if any properties are set */ 529ba1637f8Smh138676 for (j = 0; mprops[i][j].ip_name != NULL; j++) { 5307c478bd9Sstevel@tonic-gate if (mprops[i][j].ip_error != IVE_UNSET) 5317c478bd9Sstevel@tonic-gate break; 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 534ba1637f8Smh138676 if (mprops[i][j].ip_name == NULL) { 5357c478bd9Sstevel@tonic-gate /* an unspecified method */ 5367c478bd9Sstevel@tonic-gate if ((instance_method_t)i == IM_START) { 5377c478bd9Sstevel@tonic-gate error_msg(gettext( 5387c478bd9Sstevel@tonic-gate "Unspecified %s method for instance %s"), 5397c478bd9Sstevel@tonic-gate START_METHOD_NAME, fmri); 5407c478bd9Sstevel@tonic-gate valid = B_FALSE; 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate } else if (mprops[i][MP_EXEC].ip_error == IVE_UNSET) { 5437c478bd9Sstevel@tonic-gate error_msg(gettext("Missing %s property from method %s " 5447c478bd9Sstevel@tonic-gate "of instance %s"), PR_EXEC_NAME, 5457c478bd9Sstevel@tonic-gate methods[(instance_method_t)i].name, fmri); 5467c478bd9Sstevel@tonic-gate valid = B_FALSE; 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate 550cc7641ccSDan McDonald if (!valid) { 5517c478bd9Sstevel@tonic-gate destroy_basic_cfg(*cfg); 552cc7641ccSDan McDonald *cfg = NULL; 553cc7641ccSDan McDonald } 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate return (valid); 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate void 5597c478bd9Sstevel@tonic-gate destroy_instance_cfg(instance_cfg_t *cfg) 5607c478bd9Sstevel@tonic-gate { 5617c478bd9Sstevel@tonic-gate if (cfg != NULL) { 5627c478bd9Sstevel@tonic-gate destroy_basic_cfg(cfg->basic); 5637c478bd9Sstevel@tonic-gate destroy_method_infos(cfg->methods); 5647c478bd9Sstevel@tonic-gate free(cfg); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate /* 5697c478bd9Sstevel@tonic-gate * Returns an allocated instance_cfg_t representation of an instance's 5707c478bd9Sstevel@tonic-gate * configuration read from the repository. If the configuration is invalid, a 5717c478bd9Sstevel@tonic-gate * repository error occurred, or a memory allocation occurred returns NULL, 5727c478bd9Sstevel@tonic-gate * else returns a pointer to the allocated instance_cfg_t. 5737c478bd9Sstevel@tonic-gate */ 5747c478bd9Sstevel@tonic-gate instance_cfg_t * 5757c478bd9Sstevel@tonic-gate read_instance_cfg(const char *fmri) 5767c478bd9Sstevel@tonic-gate { 5777c478bd9Sstevel@tonic-gate uint_t retries; 5787c478bd9Sstevel@tonic-gate inetd_prop_t *bprops; 5797c478bd9Sstevel@tonic-gate inetd_prop_t *mprops[NUM_METHODS]; 5807c478bd9Sstevel@tonic-gate instance_cfg_t *ret = NULL; 5817c478bd9Sstevel@tonic-gate scf_error_t err; 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate if ((ret = calloc(1, sizeof (instance_cfg_t))) == NULL) 5847c478bd9Sstevel@tonic-gate return (NULL); 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate for (retries = 0; retries <= REP_OP_RETRIES; retries++) { 5877c478bd9Sstevel@tonic-gate if (make_handle_bound(rep_handle) == -1) { 5887c478bd9Sstevel@tonic-gate err = scf_error(); 5897c478bd9Sstevel@tonic-gate goto read_error; 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate if (read_inst_props(fmri, &bprops, mprops, &err) == 0) 5937c478bd9Sstevel@tonic-gate break; 5947c478bd9Sstevel@tonic-gate if (err != SCF_ERROR_CONNECTION_BROKEN) 5957c478bd9Sstevel@tonic-gate goto read_error; 5967c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(rep_handle); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate if (retries > REP_OP_RETRIES) 5997c478bd9Sstevel@tonic-gate goto read_error; 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate /* 6027c478bd9Sstevel@tonic-gate * Switch off validation of the start method's exec string, since 6037c478bd9Sstevel@tonic-gate * during boot the filesystem it resides on may not have been 6047c478bd9Sstevel@tonic-gate * mounted yet, which would result in a false validation failure. 6057c478bd9Sstevel@tonic-gate * We'll catch any real errors when the start method is first run 6067c478bd9Sstevel@tonic-gate * in passes_basic_exec_checks(). 6077c478bd9Sstevel@tonic-gate */ 6087c478bd9Sstevel@tonic-gate bprops[PT_EXEC_INDEX].ip_error = IVE_UNSET; 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate if ((!valid_inst_props(fmri, bprops, mprops, &ret->basic)) || 6117c478bd9Sstevel@tonic-gate (populate_defaults(bprops, ret->basic) != 0) || 6127c478bd9Sstevel@tonic-gate (create_method_infos(fmri, mprops, ret->methods) != 0)) { 6137c478bd9Sstevel@tonic-gate destroy_instance_cfg(ret); 6147c478bd9Sstevel@tonic-gate ret = NULL; 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate destroy_inst_props(bprops, mprops); 6187c478bd9Sstevel@tonic-gate return (ret); 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate read_error: 6217c478bd9Sstevel@tonic-gate error_msg(gettext( 6227c478bd9Sstevel@tonic-gate "Failed to read the configuration of instance %s: %s"), fmri, 6237c478bd9Sstevel@tonic-gate scf_strerror(err)); 6247c478bd9Sstevel@tonic-gate free(ret); 6257c478bd9Sstevel@tonic-gate return (NULL); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* 6297c478bd9Sstevel@tonic-gate * Returns a pointer to an allocated method context for the specified method 6307c478bd9Sstevel@tonic-gate * of the specified instance if it could retrieve it. Else, if there were 6317c478bd9Sstevel@tonic-gate * errors retrieving it, NULL is returned and the pointer referenced by 6327c478bd9Sstevel@tonic-gate * 'errstr' is set to point at an appropriate error string. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate struct method_context * 635870ad75aSSean Wilcox read_method_context(const char *inst_fmri, const char *method, const char *path) 6367c478bd9Sstevel@tonic-gate { 6377c478bd9Sstevel@tonic-gate scf_instance_t *scf_inst = NULL; 6387c478bd9Sstevel@tonic-gate struct method_context *ret; 6397c478bd9Sstevel@tonic-gate uint_t retries; 640870ad75aSSean Wilcox mc_error_t *tmperr; 641870ad75aSSean Wilcox char *fail; 6427c478bd9Sstevel@tonic-gate 643870ad75aSSean Wilcox fail = gettext("Failed to retrieve method context for the %s method of " 644870ad75aSSean Wilcox "instance %s : %s"); 6457c478bd9Sstevel@tonic-gate for (retries = 0; retries <= REP_OP_RETRIES; retries++) { 6467c478bd9Sstevel@tonic-gate if (make_handle_bound(rep_handle) == -1) 6477c478bd9Sstevel@tonic-gate goto inst_failure; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate if (((scf_inst = scf_instance_create(rep_handle)) != NULL) && 6507c478bd9Sstevel@tonic-gate (scf_handle_decode_fmri(rep_handle, inst_fmri, NULL, NULL, 6517c478bd9Sstevel@tonic-gate scf_inst, NULL, NULL, SCF_DECODE_FMRI_EXACT) == 0)) 6527c478bd9Sstevel@tonic-gate break; 6537c478bd9Sstevel@tonic-gate if (scf_error() != SCF_ERROR_CONNECTION_BROKEN) { 6547c478bd9Sstevel@tonic-gate scf_instance_destroy(scf_inst); 6557c478bd9Sstevel@tonic-gate goto inst_failure; 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate (void) scf_instance_destroy(scf_inst); 6597c478bd9Sstevel@tonic-gate scf_inst = NULL; 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(rep_handle); 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate if (retries > REP_OP_RETRIES) 6647c478bd9Sstevel@tonic-gate goto inst_failure; 6657c478bd9Sstevel@tonic-gate 666870ad75aSSean Wilcox if ((tmperr = restarter_get_method_context( 6677c478bd9Sstevel@tonic-gate RESTARTER_METHOD_CONTEXT_VERSION, scf_inst, NULL, method, path, 6687c478bd9Sstevel@tonic-gate &ret)) != NULL) { 6697c478bd9Sstevel@tonic-gate ret = NULL; 670870ad75aSSean Wilcox error_msg(fail, method, inst_fmri, tmperr->msg); 671870ad75aSSean Wilcox restarter_mc_error_destroy(tmperr); 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate scf_instance_destroy(scf_inst); 6757c478bd9Sstevel@tonic-gate return (ret); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate inst_failure: 6787c478bd9Sstevel@tonic-gate /* 6797c478bd9Sstevel@tonic-gate * We can rely on this string not becoming invalid 6807c478bd9Sstevel@tonic-gate * since we don't call bind_textdomain_codeset() or 6817c478bd9Sstevel@tonic-gate * setlocale(3C) after initialization. 6827c478bd9Sstevel@tonic-gate */ 683870ad75aSSean Wilcox error_msg(fail, method, inst_fmri, 684870ad75aSSean Wilcox gettext("failed to get instance from repository")); 6857c478bd9Sstevel@tonic-gate return (NULL); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* 6897c478bd9Sstevel@tonic-gate * Reads the value of the enabled property from the named property group 6907c478bd9Sstevel@tonic-gate * of the given instance. 6917c478bd9Sstevel@tonic-gate * If an error occurs, the SCF error code is returned. The possible errors are: 6927c478bd9Sstevel@tonic-gate * - SCF_ERROR_INVALID_ARGUMENT: The enabled property is not a boolean. 6937c478bd9Sstevel@tonic-gate * - SCF_ERROR_NONE: No value exists for the enabled property. 6947c478bd9Sstevel@tonic-gate * - SCF_ERROR_CONNECTION_BROKEN: Repository connection broken. 6957c478bd9Sstevel@tonic-gate * - SCF_ERROR_NOT_FOUND: The property wasn't found. 6967c478bd9Sstevel@tonic-gate * - SCF_ERROR_NO_MEMORY: allocation failure. 6977c478bd9Sstevel@tonic-gate * Else 0 is returned and 'enabled' set appropriately. 6987c478bd9Sstevel@tonic-gate */ 6997c478bd9Sstevel@tonic-gate static scf_error_t 7007c478bd9Sstevel@tonic-gate read_enable_prop(const char *fmri, boolean_t *enabled, const char *pg) 7017c478bd9Sstevel@tonic-gate { 7027c478bd9Sstevel@tonic-gate scf_simple_prop_t *sp; 7037c478bd9Sstevel@tonic-gate uint8_t *u8p; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate if ((sp = scf_simple_prop_get(rep_handle, fmri, pg, 7067c478bd9Sstevel@tonic-gate SCF_PROPERTY_ENABLED)) == NULL) 7077c478bd9Sstevel@tonic-gate return (scf_error()); 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate if ((u8p = scf_simple_prop_next_boolean(sp)) == NULL) { 7107c478bd9Sstevel@tonic-gate scf_simple_prop_free(sp); 7117c478bd9Sstevel@tonic-gate return (scf_error()); 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate *enabled = (*u8p != 0); 7157c478bd9Sstevel@tonic-gate scf_simple_prop_free(sp); 7167c478bd9Sstevel@tonic-gate return (0); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate /* 7207c478bd9Sstevel@tonic-gate * Reads the enabled value for the given instance FMRI. The read value 7217c478bd9Sstevel@tonic-gate * is based on a merge of the 'standard' enabled property, and the temporary 7227c478bd9Sstevel@tonic-gate * override one; the merge involves using the latter properties value if 7237c478bd9Sstevel@tonic-gate * present, else resporting to the formers. If an error occurs -1 is returned, 7247c478bd9Sstevel@tonic-gate * else 0 is returned and 'enabled' set approriately. 7257c478bd9Sstevel@tonic-gate */ 7267c478bd9Sstevel@tonic-gate int 7277c478bd9Sstevel@tonic-gate read_enable_merged(const char *fmri, boolean_t *enabled) 7287c478bd9Sstevel@tonic-gate { 7297c478bd9Sstevel@tonic-gate uint_t retries; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate for (retries = 0; retries <= REP_OP_RETRIES; retries++) { 7327c478bd9Sstevel@tonic-gate if (make_handle_bound(rep_handle) == -1) 7337c478bd9Sstevel@tonic-gate goto gen_fail; 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate switch (read_enable_prop(fmri, enabled, SCF_PG_GENERAL_OVR)) { 7367c478bd9Sstevel@tonic-gate case 0: 7377c478bd9Sstevel@tonic-gate debug_msg("read %d from override", *enabled); 7387c478bd9Sstevel@tonic-gate return (0); 7397c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 7407c478bd9Sstevel@tonic-gate break; 7417c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 7427c478bd9Sstevel@tonic-gate case SCF_ERROR_NONE: 7437c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 7447c478bd9Sstevel@tonic-gate switch (read_enable_prop(fmri, enabled, 7457c478bd9Sstevel@tonic-gate SCF_PG_GENERAL)) { 7467c478bd9Sstevel@tonic-gate case 0: 7477c478bd9Sstevel@tonic-gate debug_msg("read %d from non_override", 7487c478bd9Sstevel@tonic-gate *enabled); 7497c478bd9Sstevel@tonic-gate return (0); 7507c478bd9Sstevel@tonic-gate case SCF_ERROR_CONNECTION_BROKEN: 7517c478bd9Sstevel@tonic-gate break; 7527c478bd9Sstevel@tonic-gate case SCF_ERROR_NOT_FOUND: 7537c478bd9Sstevel@tonic-gate case SCF_ERROR_NONE: 7547c478bd9Sstevel@tonic-gate case SCF_ERROR_INVALID_ARGUMENT: 7557c478bd9Sstevel@tonic-gate error_msg(gettext("Missing %s property/value " 7567c478bd9Sstevel@tonic-gate "for instance %s"), SCF_PROPERTY_ENABLED, 7577c478bd9Sstevel@tonic-gate fmri); 7587c478bd9Sstevel@tonic-gate return (-1); 7597c478bd9Sstevel@tonic-gate default: 7607c478bd9Sstevel@tonic-gate goto gen_fail; 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate break; 7637c478bd9Sstevel@tonic-gate default: 7647c478bd9Sstevel@tonic-gate goto gen_fail; 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate (void) scf_handle_unbind(rep_handle); 7687c478bd9Sstevel@tonic-gate continue; 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate gen_fail: 7727c478bd9Sstevel@tonic-gate error_msg(gettext("Failed to read the %s property of instance %s: %s"), 7737c478bd9Sstevel@tonic-gate SCF_PROPERTY_ENABLED, fmri, scf_strerror(scf_error())); 7747c478bd9Sstevel@tonic-gate return (-1); 7757c478bd9Sstevel@tonic-gate } 776eed64e98Sgm209912 777eed64e98Sgm209912 /* 778eed64e98Sgm209912 * Refresh the value of debug property under the property group "config" 779eed64e98Sgm209912 * for network/inetd service. 780eed64e98Sgm209912 */ 781eed64e98Sgm209912 void 782eed64e98Sgm209912 refresh_debug_flag(void) 783eed64e98Sgm209912 { 784eed64e98Sgm209912 scf_simple_prop_t *sprop; 785eed64e98Sgm209912 uint8_t *tmp_bool; 786eed64e98Sgm209912 787eed64e98Sgm209912 if ((sprop = scf_simple_prop_get(rep_handle, INETD_INSTANCE_FMRI, 788eed64e98Sgm209912 PG_NAME_APPLICATION_CONFIG, PR_NAME_DEBUG_FLAG)) == NULL) { 789eed64e98Sgm209912 error_msg(gettext("Unable to read %s property from %s property " 790eed64e98Sgm209912 "group. scf_simple_prop_get() failed: %s"), 791eed64e98Sgm209912 PR_NAME_DEBUG_FLAG, PG_NAME_APPLICATION_CONFIG, 792eed64e98Sgm209912 scf_strerror(scf_error())); 793eed64e98Sgm209912 return; 794eed64e98Sgm209912 } else if ((tmp_bool = scf_simple_prop_next_boolean(sprop)) == NULL) { 795eed64e98Sgm209912 error_msg(gettext("Unable to read %s property for %s service. " 796eed64e98Sgm209912 "scf_simple_prop_next_boolean() failed: %s"), 797eed64e98Sgm209912 PR_NAME_DEBUG_FLAG, INETD_INSTANCE_FMRI, 798eed64e98Sgm209912 scf_strerror(scf_error())); 799eed64e98Sgm209912 } else { 800eed64e98Sgm209912 debug_enabled = ((*tmp_bool == 0) ? B_FALSE : B_TRUE); 801eed64e98Sgm209912 } 802eed64e98Sgm209912 803eed64e98Sgm209912 scf_simple_prop_free(sprop); 804eed64e98Sgm209912 } 805